0

I'm using Java Socket to send a file to server and then get a response back. The problem is every time i try to read the response from server, it makes the file-reading part of the server hang. I really need your help on what's going on here?

Here is SERVER code:

ServerSocket server = new ServerSocket(PORT);
Socket client = server.accept();
BufferedInputStream netInStream = new BufferedInputStream(client.getInputStream());
BufferedOutputStream netOutStream = new BufferedOutputStream(client.getOutputStream());

String outFileName = "output/test";
File outputFile = new File(outFileName);
if (!outputFile.exists()) {
    outputFile.getParentFile().mkdirs();
}
FileOutputStream fileOutStream = new FileOutputStream(outputFile);
BufferedOutputStream bufOutStream = new BufferedOutputStream(fileOutStream);

// read file from client and save
int bytesRead = 0;
byte[] buffer = new byte[1024];
while ((bytesRead = netInStream.read(buffer)) > 0) {
    bufOutStream.write(buffer, 0, bytesRead);
    bufOutStream.flush();
    Log.line("Bytes read: " + bytesRead);
}
// clean up file IO
// ...

// send response to client
netOutStream.write("File received by server".getBytes());
netOutStream.flush();

// clean up network IO
// ...

CLIENT code:

Socket client = new Socket(DOMAIN_SERVER, PORT_SERVER);
BufferedOutputStream netOutStream = new BufferedOutputStream(client.getOutputStream());
BufferedInputStream netInStream = new BufferedInputStream(client.getInputStream());

String inFileName = "input/test";
File file = new File(inFileName);
if (!file.exists()) {
    client.close();
    return;
}
FileInputStream fileInSream = new FileInputStream(file);
BufferedInputStream bufInStream = new BufferedInputStream(fileInSream);

// read and send file to server
int bytesRead = 0;
byte[] buffer = new byte[1024];
while ((bytesRead = bufInStream.read(buffer)) > 0) {
    netOutStream.write(buffer, 0, bytesRead);
    netOutStream.flush();
    Log.line("Bytes sent: " + bytesRead);
}
// clean up file IO
// ...

// read response from server
StringBuilder res = new StringBuilder();
byte[] charBuf = new byte[128];
int msgBytesRead = 0;
while ((msgBytesRead = netInStream.read(charBuf)) > 0) {
    res.append(new String(charBuf, 0, msgBytesRead));
}
Log.line(res.toString());

// clean up network IO
// ...

The flow is, client sends a file to server, server reads the file and saves to its local storage then the server sends a response string to client, the client reads the response and prints it out on the screen.

If the code is like above, the server will not exit the while-loop and hang, therefor the client second while-loop doesn't read anything and hang, too. But if i comment/remove the client second while-loop, both programs run and no hang occurs. File transfer is also success.

  • So i managed to fix this by sending file size data to server, and provide a logic in server to break the loop after the read-bytes exceed the file size. But i still don't know why my above code behave like that, i still need an answer from you guys. – Đào Thiện Tuấn Jul 07 '19 at 12:12

1 Answers1

1

Your expectation is that read returns with no data once the server is done sending the file. This expectation is wrong. read will only return with no data if the server has closed the TCP connection and the flush you show does not close the connections but only makes sure that all buffered data are written to the TCP connection.

This means the server can still send more data after the flush and that's why your client is hanging in the read and waiting for more data.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • Actually the client is sending the file, but the same logic can also be applied, right ? – Đào Thiện Tuấn Jul 07 '19 at 14:42
  • @ĐàoThiệnTuấn: yes, same logic. `read` only returns when either data are to read or the connection is closed. There is no implicit `end of file` or similar indicator in TCP, only end of connection. – Steffen Ullrich Jul 07 '19 at 15:15