部分源码:
fout = new FileOutputStream(file);
din = new DataInputStream(socket.getInputStream());
byte[] bytes = new byte[1024];
int length = 0;
while ((length = din.read(bytes, 0, bytes.length)) != -1) {
fout.write(bytes, 0, length);
fout.flush();
System.out.println(length);
}
System.out.println("---------文件接收成功---------");
如上,当文件写入完成后,发现服务器一直不打印
"---------文件接收成功---------"
得知length一直不等于-1导致跳不出循环
然后我试着在循环中打印了length,结果也只打印了一次就停止了。
之后又查看了下read的源码,发现如果按源码所说当读到文件结束后就会返回-1。
因此得出结论是din流尚未结束,然后往上追溯可看到din是由socket.getInputStream()获得的,
因此可以知道din流一直在等待客户端继续发送文件或信息,也就是read()方法在这个时候阻塞了。
总结下就是客户端和服务器建立了一条链接,客户端把文件发送完后就走了,服务器也不知道客户端发完了没,一直在傻傻的等,于是阻塞就发生了。
那我们怎么解决阻塞呢?
上网查了下有以下几种方法:
1、客户端告诉服务端我发完了,在发送的那一端(也就是客户端)调用socket.shutdownOutput();这样服务器端就知道文件发送结束了,read方法就会返回-1
2、发送数据时,在数据首部给定文件长度,当接受完给定长度后手动跳出循环。
3、在服务器端设置超时,比如3秒:
socket.setSoTimeout(3000);
如果read()方法在固定时间内没有读到数据的话就会抛出异常