I'm creating a server to receive both text and binary data from clients. It works with text data as well as the first time receiving binary file, but after this it didn't continue to reading data and throw an exception. Here is my server code:
public class ConnectedProcessThread implements Runnable{
private final Socket socket;
public ConnectedProcessThread(Socket clientSocket){
socket = clientSocket;
}
public void run(){
DataInputStream dis = null;
try{
while(true) {
dis = new DataInputStream(socket.getInputStream());
String meta = dis.readUTF();
Log.i("Data received", meta);
if(meta.equalsIgnoreCase("Text")){
String message = dis.readUTF();
Log.i("Data received", message);
}else if(meta.equalsIgnoreCase("Binary")){
InputStream is = socket.getInputStream();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
byte[] buf = new byte[4096];
int len;
while((len=is.read(buf))>-1){
stream.write(buf,0,len);
}
stream.flush();
//read object input
try {
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(stream.toByteArray()));
byte[] buffer = (byte[])ois.readObject();
FileOutputStream fos = new FileOutputStream("/storage/emulated/0/DCIM/IMG-Saved.jpeg");
fos.write(buffer);
}catch (ClassNotFoundException e){
e.printStackTrace();
}
finally {
Log.i("Binary_Transfer","File created");
}
}
}
} catch (IOException e){
e.printStackTrace();
}finally {
Log.i("Client_Socket","Stream will close");
if(dis!=null){
try {
dis.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
}
For both text and binary data, before sending the data, client will sent text meta-data to inform the server the data is text or binary. But after receiving a file(image), it throws an EOFException at line: String meta = dis.readUTF(); I guessed it happened because after reading and writing binary file, the thread continues to loop so DataInputStream will read again, and now there's nothing to receive so readUTF() throws EOFException. I tried to send a meta-data from client after sending the binary file to let DataInputStream can read something and not throw an exception, but it didn't work, the client did send the meta-data but the server still throws EOFException. Anyone knows what the problem is? Thanks so much.
Here is my send binary method from client:
public void sendBinaryData(byte[] binaryData){
if(dos!=null && socket!=null){
try {
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(binaryData);
Log.d("Binary_Transfer", "C: Sent.");
oos.close();
dos.writeUTF("Binary_End");
dos.flush();
}catch (Exception e){
Log.e("File_Exception",e.toString());
}
}
}
Because when you start reading the binary data, you enter a loop that only terminates at end of stream, i.e. when the peer disconnects:
while((len=is.read(buf))>-1){
stream.write(buf,0,len);
}
At that point you are at the end of the stream. There was no more data, there is no more data, and there never will be any more data.
You need to completely remove this part:
InputStream is = socket.getInputStream();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
byte[] buf = new byte[4096];
int len;
while((len=is.read(buf))>-1){
stream.write(buf,0,len);
}
stream.flush();
There is rarely any point in reading things into ByteArrayOutputStreams
anyway, and this is no exception. Just remove that completely, and change the next part:
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(stream.toByteArray()));
to
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
and continue as you are already. However you have another problem:
oos.close();
This closes the socket. So the next part:
dos.writeUTF("Binary_End");
dos.flush();
cannot possibly work. Just flush the ObjectOutputStream
instead of closing it.
But I would strongly suggest you discard the DataInput/OutputStreams
and use a single ObjectInput/OutputStream
for the life of the socket, at both ends.