I am developing wifi direct based file transfer application. I can see that the transfer speed using TCP socket is not satisfactory. The speed is normally 1Mbps. Whenever I analyze the data transfer graph, I can see a lot of spikes and many seconds are with no data transfer at all. I know the transfer speed should be much higher (may be 20-30Mbps)
Please help me in increasing the transfer speed.
The serversocket that accepts the connection is
private void serverTask() {
Log.v(TAG, "server task");
try {
serverRunning = true;
ServerSocket serverSocket = new ServerSocket(
DeviceDetailFragment.PORT);
serverSocket.setReceiveBufferSize(TCP_BUFFER_SIZE);
Socket client = serverSocket.accept();
BufferedInputStream inputstream = new BufferedInputStream(
client.getInputStream());
// new BufferedInputStream(client.getInputStream(), 8 * 1024);
BufferedReader bufferedStream = new BufferedReader(
new InputStreamReader(inputstream));
fileName = bufferedStream.readLine();
fileSizeInBytes = bufferedStream.readLine();
fileMime = bufferedStream.readLine();
f = new File(Globals.fileSavingLocation + fileName);
File dirs = new File(f.getParent());
if (!dirs.exists())
dirs.mkdirs();
if (f.exists()) {
f.delete();
}
f.createNewFile();
IOUtils.copy(inputstream, new FileOutputStream(f));
serverSocket.close();
}
isSuccessful = true;
} catch (IOException e) {
isSuccessful = false;
Log.e(TAG, e.getMessage());
}
serverRunning = false;
}
And the client that sends the data has following code:
private void clientTask(Intent intent) {
String fileUri = intent.getExtras().getString(EXTRAS_FILE_PATH);
String host = intent.getExtras().getString(EXTRAS_ADDRESS);
String fileName = intent.getExtras().getString(FILE_NAME);
String fileMimeType = intent.getExtras().getString(FILE_MIME_TYPE);
final long sizeInBytes = intent.getExtras().getLong(FILE_SIZE);
Socket socket = new Socket();
int port = intent.getExtras().getInt(EXTRAS_PORT);
try {
socket.setSendBufferSize(TCP_BUFFER_SIZE);
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)),
SOCKET_TIMEOUT);
BufferedOutputStream stream = new BufferedOutputStream(
socket.getOutputStream());
ContentResolver cr = FileTransferService.this
.getApplicationContext().getContentResolver();
InputStream is = null;
BufferedWriter bufferStream = new BufferedWriter(
new OutputStreamWriter(stream));
bufferStream.write(fileName);
bufferStream.newLine();
bufferStream.flush();
bufferStream.write(String.valueOf(sizeInBytes));
bufferStream.newLine();
bufferStream.flush();
bufferStream.write(fileMimeType);
bufferStream.newLine();
bufferStream.flush();
try {
is = new BufferedInputStream(cr.openInputStream(Uri
.parse(fileUri)));
} catch (FileNotFoundException e) {
isSuccessful = false;
}
IOUtils.copy(is, stream);
isSuccessful = true;
} catch (IOException e) {
Log.e(TAG, e.getMessage());
isSuccessful = false;
} finally {
if (socket != null) {
if (socket.isConnected()) {
try {
socket.close();
} catch (IOException e) {
// Give up
e.printStackTrace();
}
}
}
}
The value of TCP_BUFFER_SIZE is set to 1024*512.
I have tried a lot altering the value of TCP_BUFFER_SIZE but with no luck. I replaced my implementation of copying stream by Apache Commons IOUtils.
Help me out
Update:
Please see the following transfer graph
It seems that you are overloading the buffer, from the setReceiveBufferSize() javadoc
It is possible to change the value subsequently, by calling
Socket.setReceiveBufferSize(int). However, if the application wishes
to allow a receive window larger than 64K bytes, as defined by RFC1323
then the proposed value must be set in the ServerSocket before it is
bound to a local address. This implies, that the ServerSocket must be
created with the no-argument constructor, then setReceiveBufferSize()
must be called and lastly the ServerSocket is bound to an address by
calling bind().
I would try a simple data transfer using a plain Socket without using files.
Have a simple server which sends 100 MB of empty data when you connect. Have the client read that data as fast as it can a report the throughput it got. On the same machine you should see over 100 MB/s easily. Once this gives a good number try it on an android client.
Related
This question already has answers here:
How can I fix 'android.os.NetworkOnMainThreadException'?
(66 answers)
Closed 5 years ago.
In my application I am using TCP socket connection to connect android device to server. Socket is working normally on every device, except devices with Android 7+ where I get "Socket is closed" error.
Socket problems happen on Nexus 6P and Samsung s7!
I am using socket in Runnable in a Service, initializing socket with:
public class ClientThread implements Runnable {
public void run() {
while (true) {
try {
DataHandler.indicator.set(false);
mRun = true;
if (DataHandler.DOMAIN_IP.contains(":")) {
serverAddr = Inet4Address.getByName(DataHandler.DOMAIN_IP.split(":")[0]);
} else
serverAddr = Inet4Address.getByName(DataHandler.DOMAIN_IP.replace(":3030", ""));
Log.i("Socket", "Connecting");
socket = new Socket(serverAddr, SERVERPORT);
socket.setKeepAlive(true);
socket.setSoLinger(true, 1);
socket.setSoTimeout(30000);
DataHandler.IP_ADDRESS = socket.getLocalAddress().toString().split("/")[1];
DataInputStream dis = new DataInputStream(socket.getInputStream());
connectionDelay = MIN_WAIT;
Log.i("Socket", "Connected");
String serverMessage = "";
byte[] array = new byte[1024];
while (mRun) {
int firstbye = dis.read();
int arraylength = dis.available();
array = new byte[arraylength];
dis.read(array, 0, array.length);
String str = new String(new byte[]{(byte) firstbye});
serverMessage += str + EncodingUtils.getString(array, "UTF-8");
DataHandler.indicator.set(true);
if (firstbye != -1) {
String mstString = new String(serverMessage);
serverMessage = "";
onReceive(NotificationService.this, mstString);
} else { // if (serverMessage.equalsIgnoreCase("")) {
try {
socket.close();
Log.e("Socket", "Disconnect");
socket = null;
stopClient();
} catch (Exception e) {
e.getMessage();
}
serverMessage = null;
DataHandler.indicator.set(false);
continue;
}
}
} catch (UnknownHostException e) {
isNeedtoWrite = true;
} catch (IOException e1) {
isNeedtoWrite = true;
DataHandler.indicator.set(false);
} finally {
try {
socket.close();
DataHandler.indicator.set(false);
Log.e("Socket", "Disconnect");
socket = null;
stopClient();
} catch (Exception e) {
e.getMessage();
}
}
try {
connectionDelay = Math.min(MAX_WAIT, RandomUtils.nextInt(MIN_WAIT, (int) (connectionDelay * BACKOFF_RATE)));
Log.i("SocketSleep", String.valueOf(connectionDelay));
Thread.sleep(connectionDelay);
DataHandler.indicator.set(false);
} catch (InterruptedException e) {
e.getMessage();
}
}
}
}
Before code reaches setSoTimeout it gets to exception.
I have tried a different application which uses same Socket logic and on start it worked normally and then it just dropped unexpectedly and it doesn't work anymore. I checked on wireshark and this happens:
Does anyone have any clue what could the problem be?
Bux fix:
Due to a bug in previous versions of Android, the system did not flag writing to a TCP socket on the main thread as a strict-mode violation. Android 7.0 fixes this bug. Apps that exhibit this behavior now throw an android.os.NetworkOnMainThreadException. Generally, performing network operations on the main thread is a bad idea because these operations usually have a high latency that causes ANRs and jank.
And link to documentation.
I found out what the problem was... I actually HAD some code which called
socket.getOutputStream().write(GetSendString());
outside my thread, and this was causing socket to disconnect / crash because of NetworkOnMainthread error, but I didn't have Exception handled properly!
Maybe the problem is caused by reading the InputStream using .read command.
Try using BufferedReader, and similar for the OutputStream :
BufferedReader dis = new BufferedReader(
new InputStreamReader( socket.getInputStream() ));
PrintWriter os_buffer = new PrintWriter(
new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
I build a TCP multicast chat application using asynctask.
I am also trying to order the message in FIFO and causal order.
However, when I try to send a lot of messages simultaneously for testing, it misses some messages but I can't find the reason.
I have tried as hard as I can to improve the performance of the program because I thought the performance could be the reason. but still having the same issue.
I attached some important part of my code.
Most of all,
private class ServerTask extends AsyncTask<ServerSocket, String, Void> {
#Override
protected Void doInBackground(ServerSocket... sockets){
ServerSocket serverSocket = sockets[0];
Socket socket = new Socket();
try {
while(true) {
socket = serverSocket.accept();
InputStream inputstream = socket.getInputStream();
DataInputStream in = new DataInputStream(new BufferedInputStream(inputstream));
String msg = ""+in.readUTF();
String time = ""+in.readUTF();
String temp = time+"||"+msg;
publishProgress(temp);
in.close();
}} catch (IOException e) {
e.printStackTrace();
} finally{
try {
socket.close();
serverSocket.close();////
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
Here is onProgressUpdate.
protected void onProgressUpdate(String...strings) {
/*
* The following code displays what is received in doInBackground().
*/
String strReceived = strings[0].trim();
TextView remoteTextView = (TextView) findViewById(R.id.textView1);
remoteTextView.append(strReceived + "\t\n");
try {
sequencer(strReceived);
} catch (ParseException e) {
e.printStackTrace();
}
return;
}
}
..
private class ClientTask extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... msgs) {
Date currentDate= new Date();
Timestamp time = new Timestamp(currentDate.getTime());
Message temp = new Message(myPort, msgs[0], time);////
try {
for(int i = 0; i <= 2; i++) {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(InetAddress.getByAddress(new byte[]{10, 0, 2, 2}),
Integer.parseInt(REMOTE_PORTS[i])), 1000);
socket.setTcpNoDelay(true);
OutputStream outputStream = socket.getOutputStream();
DataOutputStream o = new DataOutputStream(new BufferedOutputStream(outputStream));
o.writeUTF(msgs[0]);
o.writeUTF(""+time);
o.flush();////
socket.close();
}
}
catch (UnknownHostException e) {
Log.e(TAG, "ClientTask UnknownHostException");
} catch (IOException e) {
Log.e(TAG, "ClientTask socket IOException");
}
return null;
}
Can you find the part causes the problem?
Sequencing / Queueing /Acknowledgement all these things are part of TCP so it is done by the protocol itself so you do not need to do all those explicitly from your code. There are still some parts of your code that can be improved. Like:
String time = received.split("\\|\\|")[0];
String msgToSend = received.split("\\|\\|")[1];
//Instead of doing this, its better to do this:
String peices[]=received.split("\\|\\|");
String msgToSend=peices[1];
String time=peices[0]
Also you can check if you are receiving all the raw messages and if its during the parsing process the messages are getting lost using a log:
Log.d("RAW_MESSAGE","Message Received: "+temp); //in your doInBackground
If you get all the messages that you send in this log, then there is nothing wrong with the protocol or the sending/receiving process rather there is a problem while you are processing the message. Also for these types of use-cases, try using the Service component rather than AsyncTask.
I hope this helps.
First of all multicast is over UDP, not TCP.
And if you want to create a multicast app, you should use multicastsocket
http://developer.android.com/reference/java/net/MulticastSocket.html
I need some advice and help troubleshooting a client/server interaction for a cellular modem project I'm working on. The client and server are written in Java.
The questions I need some advice on are as follows:
(1) I'm seeking advice on whether the approach I'm taking is going to scale up for large files (Code to follow) especially in the context of a cellular network where the network can drop out unexpectedly. Large files being ~1GB. The large file represent an image that is transferred from the server to client. This represents the worst case scenario. The base case contains files that are relatively small, containing GPS Data and Time Stamp info. These files are likely in the KB to a couple of MB range and transferred often.
(2) Need advice on troubleshooting the client/server code. Even if this approach isn't going to work for larger files, I would like to get the code working for the base case to support a proof of concept test in the near future. Software updates are not required for the proof of concept.
Background on the client/server interaction. The client contacting the server. The server detects the client request which starts a new thread to handle the client. The client transmits a serilaize Data Packet. The Data Packet contains some header info (file size, crc, file type) and a data payload. Upon receiving the data packet object, the server verifies the crc and file size match the values include in the header. The server responds with a data packet object which indicates whether the transmission was valid or not. If the client receives a valid response from the server the client sends a good bye packet to close the session. If the response was invalid from the server, the client will resend the data and will eventually quit after x failed attempts. Eventually, the client will get a set of instructions from the server which can instruct it to upload a log file, download a new .jre file, or even a new firmware image.
Here is the error that I'm getting on the server code:
Feb 16, 2013 7:36:40 AM noaa.logbook.server.ServerConnectionHandler run
SEVERE: null
java.io.EOFException
at
java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2553)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1296)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at noaa.logbook.server.ServerConnectionHandler.run(ServerConnectionHandler.java:69)
at java.lang.Thread.run(Thread.java:662)
The data arrives as the server and it looks exception occurs on the next time I tried to read an object on the objectinputstream, which is the goodbye packet.
Client Code:
public static boolean clientTransmit(Socket sockToServer, String fileName, int dataPacketType, String id, String fileTimeStamp) {
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
//TCPConnection tcpConn = null;
DataPacket packet = null;
File inputFile = new File(fileName);
boolean fileExists = inputFile.exists();
int size = 0;
int failedAttempts = 0;
String contents = null;
byte[] ref = null;
boolean success = false;
boolean bye = false;
try
{
sockToServer.setSoTimeout(5000);
if ((sockToServer.isConnected()) && (fileExists)) {
System.out.println("LogBookClientCommunications: Connected to Server");
System.out.print("Stage 0");
contents = readFile(fileName);
packet = LogBookUtilities.packageDataPacket(DataPacket.UPLOAD_DATA, contents, LogBookClient.SOFTWARE_VERSION, LogBookClient.serialNumber);
oos = new ObjectOutputStream(sockToServer.getOutputStream());
oos.writeObject(packet);
oos.flush();
System.out.println("LogBookClientCommunications: Sending DataPacket");
ois = new ObjectInputStream(sockToServer.getInputStream());
while(!success && failedAttempts < 3) {
Object object = ois.readObject();
if (object instanceof DataPacket) {
System.out.println("LogBookClientCommunications: Received a DataPacket Object");
DataPacket inPacket = (DataPacket)object;
byte[] compressedByteRef = inPacket.getDataArray();
boolean sizeValid = verifySize(compressedByteRef, inPacket.getLength());
boolean crcValid = verifyCRC(inPacket);
if ((sizeValid) && (crcValid)) {
System.out.println("LogBookClientCommunications: Size & CRC Valid");
String uncompressed = new String(uncompress(compressedByteRef));
String[] strRef = lookupResponsePairs(dataPacketType);
if (uncompressed.equals(strRef[0])) {
success = true;
System.out.println("LogBookClientCommunications: File arrived uncorrupted");
//tcpConn.disconnect();
} else if (uncompressed.equals(strRef[1])) {
success = false;
failedAttempts++;
System.out.println("LogBookClientCommunications: File arrived corrupted");
}
} else {
success = false;
failedAttempts++;
if (sizeValid)
System.out.println("LogBookClientCommunications: CRC InValid");
else
System.out.println("LogBookClientCommunications: Size InValid");
}
}//end if object instanceof
else {
System.out.println("LogBookClientCommunications: Not a DataPacket Object");
failedAttempts++;
}
}//while
//Close Connection by sending bye
System.out.println("LogBookClientCommunications: Sending Good Bye...");
DataPacket goodbye = LogBookUtilities.packageDataPacket(DataPacket.RESPONSE, quit", LogBookClient.SOFTWARE_VERSION, LogBookClient.serialNumber);
oos.writeObject(goodbye);
oos.flush();
}
else
{
System.out.println("LogBookClientCommunications: Failed to Connect or File Did Not Exist");
success = false;
}
}
catch (ClassNotFoundException ex) {
Logger.getLogger(LogBookUtilities.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(LogBookUtilities.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
oos.close();
ois.close();
sockToServer.close();
} catch (IOException ex) {
Logger.getLogger(LogBookUtilities.class.getName()).log(Level.SEVERE, null, ex);
}
}
return success;
}
Server connection handler code:
public void run()
{
ObjectInputStream ois = null;
ObjectOutputStream oos = null;
int failedAttempts = 0;
boolean success = false;
boolean sendResponse = false;
Socket soc = getSocket();
Object obj = new Object();
long time = System.currentTimeMillis();
DataPacket inPacket = null;
DataPacket outPacket = null;
try {
System.out.println("Server Connection Handler: Receiving Connection From - " + soc.getRemoteSocketAddress());
soc.setSoTimeout(15000);
oos = new ObjectOutputStream(soc.getOutputStream());
oos.flush();
ois = new ObjectInputStream(soc.getInputStream());
if (ois == null | oos == null) {
System.out.println("Server Connection Handler: Successfull Opened Streams");
if (ois == null) { System.out.println("Server Connection Handler: ObjectInputStream Failed to Open");}
else {System.out.println("Server Connection Handler: ObjectOutputStream Failed to Open"); }
}
while (true) {
inPacket = (DataPacket)ois.readObject();
boolean validPacket = LogBookUtilities.isPacketValid(inPacket);
if (validPacket) {
if(inPacket.getField() == DataPacket.RESPONSE) {
byte[] ref = inPacket.getDataArray();
String data = LogBookUtilities.uncompress(ref);
if (data.equalsIgnoreCase("bye")) {
System.out.println("Server Connection Handler: Bye....");
break;
}
}
else if (inPacket.getField() == DataPacket.UPLOAD_DATA) {
System.out.println("Server Connection Handler: Writing data to file");
LogBookUtilities.processClientPacket(inPacket);
System.out.println("Server Connection Handler: File Successfully Transfered");
outPacket = LogBookUtilities.makeResponse(inPacket.getField(), true, LogBookServer.SOFTWARE_VERSION, LogBookServer.ID);
sendResponse = true;
}
}
else {
if (inPacket.getField() == DataPacket.UPLOAD_DATA) {
sendResponse = true;
outPacket = LogBookUtilities.makeResponse(inPacket.getField(), true, LogBookServer.SOFTWARE_VERSION, LogBookServer.ID);
}
}
if (sendResponse) {
oos.writeObject(outPacket);
oos.flush();
}
}//end while
}
catch (ClassNotFoundException ex) {
Logger.getLogger(ServerConnectionHandler.class.getName()).log(Level.SEVERE, null, ex);
}
catch (IOException ex) {
Logger.getLogger(ServerConnectionHandler.class.getName()).log(Level.SEVERE, null, ex);
}
finally {
try {
ois.close();
oos.close();
soc.close();
}
catch (IOException ex) {
Logger.getLogger(ServerConnectionHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Server code:
public class LogBookServer
{
public static final String ID = "666666";
public static final String SOFTWARE_VERSION = "0.02";
public static final String VFILE = "vFile";
public static final String DASH = "-";
public static final String DATEXT = ".dat";
public static final int FAILED_THRESHOLD = 3;
private int port = 6767;
private String ip = "";
public int getListeningPort() {
return this.port;
}
public void setListeningPort(int port) {
this.port = port;
}
public void run()
throws Exception
{
Selector acceptSelector = SelectorProvider.provider().openSelector();
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
InetAddress lh = InetAddress.getLocalHost();
InetSocketAddress isa = new InetSocketAddress(lh, this.port);
ssc.socket().bind(isa);
SelectionKey acceptKey = ssc.register(acceptSelector, 16);
int keysAdded = 0;
while ((keysAdded = acceptSelector.select()) > 0)
{
Set readyKeys = acceptSelector.selectedKeys();
Iterator i = readyKeys.iterator();
while (i.hasNext()) {
SelectionKey sk = (SelectionKey)i.next();
i.remove();
ServerSocketChannel nextReady = (ServerSocketChannel)sk.channel();
Socket s = nextReady.accept().socket();
handleConnection(s);
}
}
}
void handleConnection(Socket socket)
{
System.out.println("hadling connection....");
ServerConnectionHandler connectionHandler = new ServerConnectionHandler(socket);
new Thread(connectionHandler).start();
}
}
In your client you have (split to diff lines for readability):
DataPacket goodbye =
LogBookUtilities.packageDataPacket(DataPacket.RESPONSE,
"quit",
LogBookClient.SOFTWARE_VERSION,
LogBookClient.serialNumber);
Then in your server you have:
if (data.equalsIgnoreCase("bye")) {
Which one of these is not like the other? ;)
Your server reads the "goodbye" packet, but doesn't recognize it, then loops again and tries to read from a closed socket. Presto, IOException.
As for your question of "scalability" ... it's not so much that as efficiency. If you're worried about the network dropping out from under you, sending serialized objects probably isn't the way to go; there's no way to resume - a partial send has to be completely resent and if it's a gig of data as you state ... that's bad. You are better off using the write() methods of OutputStream with a reasonable buffer size. This will allow you to keep track of the data that's been sent and resume a transfer once the network comes back (this will require some logic being implemented between your client and server, obviously, so that you can figure out what the server has already received in the case of a network failure).
I've written some serverside socket handling code and I'm concerned that potentially my packets are not always making it back to the client. I am logging all my events and in my log files it says I am sending the information. But the client is also logging events and in their logs they say they do not receive anything.
My code to send the data is as follows:
public void write(Packet packet) {
String data = packet.serialize();
log("Send=[" + data + "]", "Write"); // log to file
try {
_writer.write(data);
_writer.flush();
} catch (Exception ex) {
log(ex, "write");
}
}
Each socket is created on a new thread and I create my writers and readers immediately like so (in the public run method):
// _sockt is a Java Socket object
_writer = new BufferedWriter(new OutputStreamWriter(_socket
.getOutputStream()));
_reader = new SocketReader(_socket);
SocketReader is just a wrapper class I created for listening for responses and has a public read method like so:
public String read() throws IOException, SocketTimeoutException {
_socket.setSoTimeout(_timeOut);
if(_reader == null)
_reader = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
// read from the stream
return new PacketDataInputStream(_reader).read();
}
The PacketDataInputStream wrapper class:
BufferedReader _reader = null;
public PacketDataInputStream(BufferedReader reader)
{
_reader = reader;
}
public String read() throws IOException, SocketException {
StringBuilder builder = new StringBuilder();
int c = 0;
while((c = _reader.read()) != -1)
{
char ch = (char)c;
builder.append(ch);
if(ch == PacketConstants.ETX)
break;
}
if(builder.length() > 0)
return builder.toString();
else
return null;
}
The way I'm creating the actual socket listener objects is pretty standard I think:
InetAddress address = InetAddress.getByName(IP);
server = new ServerSocket( port, 0, address);
// My own manager class to handle all the sockets connected
WebSocketManager manager = new WebSocketManager(this);
Socket connection = null;
while(bContinue)
{
connection = server.accept();
if(bContinue) {
// assign the socket to a new thread and start
// that thread
manager.newSocket(connection);
} else {
connection.close();
}
}
Is is possible that I'm using the wrong objects for sending the data back.
Should I even be using a bufferedwriter and reader? I had thought that these were the best way to go but now I'm not so sure.
It's important to note that this does not happen all the time, just sporadically. It could be the clients code having bugs but I need to make sure that I'm doing it correctly before going back to them.
This code is run on a Linux Ubuntu server. Logging occurs to a text file, nothing special there. My log files show the Send="" data going back to the client and no exception so it appears as if the .write and .flush() worked? Socket connections are persistant and only closed by the client and or network issues.
UPDATE ----- Client Side code -------:
I did manage to get some of the client side code for how they are handling the send and receiving of data (just in case it's more obvious on their end). The client is actually connecting to this server via an Android device (if that helps).
Creation of socket
static final int BUFFER_SIZE = 20000; // Maximum packet size
java.net.InetAddress server = java.net.InetAddress.getByName(url);
socket = new Socket(server, port);
// Set socket options:
socket.setReceiveBufferSize(BUFFER_SIZE);
socket.setSendBufferSize(BUFFER_SIZE);
socket.setKeepAlive(true);
socket.setTcpNoDelay(true);
Sending:
try {
// Send the packet:
OutputStream stream = socket.getOutputStream();
stream.write(p.getByteArray ());
stream.flush();
// Update the time:
lastPacketSendTime = new Date ();
} catch (IOException e) {
setError("Error sending packet (" + e.getMessage() + ")", ERROR_IO);
return false;
}
Receiving:
socket.setSoTimeout(timeout);
// Get the reader:
inputStream = socket.getInputStream();
while (true) {
// Get the next character:
int value = inputStream.read();
// Check for -1, indicating that the socket is closed:
if (value == -1) {
// The socket is closed remotely, so close it locally as well:
disconnect();
inputStream = null;
return null;
}
// ... and a bunch of other stuff to handle the actual data
}
EDIT 14-Nov:
This is actually proving to be more of a problem now. Both the client logs and the server logs appear to be sending. But at times the data doesn't appear to come through or if it does it is sometimes coming through 10 - 30 - 60 second delayed.
I can provide more information if required.
When you use BufferedReaders and BufferedWriters things get buffered. How about using the input and output streams directly.. Also, writers are character based, I don't know if you need to send binary data but if so that will be a problem with writers.
I am not sure whether this will be to your any use or not.. but i am giving you the code i used for client server communication..
Client Side:
public class ClientWala {
public static void main(String[] args) throws Exception{
Boolean b = true;
Socket s = new Socket("127.0.0.1", 4444);
System.out.println("connected: "+s.isConnected());
OutputStream output = s.getOutputStream();
PrintWriter pw = new PrintWriter(output,true);
// to write data to server
while(b){
if (!b){
System.exit(0);
}
else {
pw.write(new Scanner(System.in).nextLine());
}
}
// to read data from server
InputStream input = s.getInputStream();
InputStreamReader isr = new InputStreamReader(input);
BufferedReader br = new BufferedReader(isr);
String data = null;
while ((data = br.readLine())!=null){
// Print it using sysout, or do whatever you want with the incoming data from server
}
}
}
Server Code:
import java.io.*
import java.net.*;
public class ServerTest {
ServerSocket s;
public void go() {
try {
s = new ServerSocket(44457);
while (true) {
Socket incoming = s.accept();
Thread t = new Thread(new MyCon(incoming));
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
class MyCon implements Runnable {
Socket incoming;
public MyCon(Socket incoming) {
this.incoming = incoming;
}
#Override
public void run() {
try {
PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
true);
InputStreamReader isr = new InputStreamReader(
incoming.getInputStream());
BufferedReader br = new BufferedReader(isr);
String inp = null;
boolean isDone = true;
System.out.println("TYPE : BYE");
System.out.println();
while (isDone && ((inp = br.readLine()) != null)) {
System.out.println(inp);
if (inp.trim().equals("BYE")) {
System.out
.println("THANKS FOR CONNECTING...Bye for now");
isDone = false;
s.close();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
try {
s.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new ServerTest().go();
}
}
i have a program which accepts connection from a phone that sends a byte array, i am able to test the connection when it is made , however how do i know that i am actually receiving something? how can i "see" if any thing is being sent over the socket. Because from my code below i am not able to have the resulting file "saved.jpg" created. Does this mean that it did not receive anything?
public class wpsServer {
//vars
private int svrPort = 3334;
private ServerSocket serverSocket;
private Image image = null;
public wpsServer()
{
try {
serverSocket = new ServerSocket(svrPort);
System.out.println("Server started on "+svrPort);
}
catch (IOException e) {
System.out.println("Could not listen on port: "+svrPort);
System.exit(-1);
}
}
public void listenForClient()
{
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
if(clientSocket.isConnected())
System.out.println("Connected");
byte[] pic = getPicture(clientSocket.getInputStream());
InputStream in = new ByteArrayInputStream(pic);
BufferedImage image = ImageIO.read(in);
File outputfile = new File("saved.jpg");
ImageIO.write(image, "jpg", outputfile);
}
catch (IOException e) {
System.out.println("Accept failed: "+svrPort);
System.exit(-1);
}
}
public byte[] getPicture(InputStream in) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int length = 0;
while ((length = in.read(data))!=-1) {
out.write(data,0,length);
}
return out.toByteArray();
} catch(IOException ioe) {
//handle it
}
return null;
}
}
The in.read call will only return -1 if the other end closes the socket. While the socket is alive, that call will block until more data is available.
What you need to do is change your "protocol": the client should send the array size first, then the data. The server should read that length, and stop reading the file when that's done (go back to waiting for the next file for instance).