Socket通讯读取数据时阻塞解决方案
周sir |
2017年8月25日 |
Java网络编程 |
0 条评论 | 1925
读文件时 read 读到末尾会返回 -1。但 Socket 通讯里从 InputStream 读数据,对端还没关流、暂时又没有数据时,read 会一直阻塞,只有关闭流才会返回 -1。
所以下面这种「读到 -1 才停」的写法,在 Socket 上很容易卡住:
while ((len = in.read(bytes)) != -1) {
os.write(bytes, 0, len);
os.flush();
}
一、每发一次就开关连接
每发送一次消息开启 Socket 连接,发完关闭。关流后服务端 read 就能拿到 -1,循环结束。
Socket 服务端接收消息:
ServerSocket serverSocket = new ServerSocket(port);
while(true){
socket = serverSocket.accept();
receiveMessage();//接收消息
}
Socket客户端发送消息:
socket = new Socket(host, port); //发起连接
client.sendPicture(fileDir); //发送消息
二、先发文件大小
客户端先把文件字节大小写过去,服务端累计读到的字节数,够了就 break,不必等流关闭。
Socket客户端:
dos.writeLong(file.length()); //文件字节大小
Sokcet服务端:
//读取图片大小
long picLength = dos.readLong();
//图片文件内容
byte[] bytes = new byte[128];
int len = 0;
int count = 0; //统计读取流总字节数
while ((len = in.read(bytes)) != -1) {
os.write(bytes, 0, len);
os.flush();
count = count + len;
if(count == picLength){ //接收数据大小与文件大小比较
break;
}
}
三、设置读超时
用 socket.setSoTimeout 设读超时。一段时间没数据就抛 IOException,循环被打断;处理完再把超时设回 0(无穷大)。
Socket服务端:
try {
byte[] bytes = new byte[128];
int len = 0;
socket.setSoTimeout(10); //设置socket读超时时间为10毫秒
while ((len = in.read(bytes)) != -1) {
os.write(bytes, 0, len);
os.flush();
}
} catch (IOException e) {
System.out.println("接收图片成功!");
socket.setSoTimeout(0);//设置socket读超时时间为无穷大
}
| 方案 |
做法 |
何时结束读循环 |
| 开关连接 |
发完就关 Socket |
对端关流,read 返回 -1 |
| 先发长度 |
writeLong(file.length()) |
累计字节数等于文件大小则 break |
| 读超时 |
setSoTimeout(10) |
超时抛 IOException |
一句话总结:Socket 的 read 没数据会阻塞,别只等 -1;用关连接、先传长度或 setSoTimeout 才能停下来。
转载请注明来源:Socket通讯读取数据时阻塞解决方案
我是周sir,这是我的博客。致力于分享我学会的技术和优秀的文章。微信公众号 “周sir专栏” 欢迎大家关注。