read方法阻塞的解决
转载自别人的博客
- 在网络编程中,读取数据时遇到了该问题:服务器端运行到read方法停住了,不再往后运行。
代码如下:
客户端:
public class SocketClient {public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException {Socket client = new Socket("localhost",8888);OutputStream out = client.getOutputStream();InputStream input = client.getInputStream();out.write("sender say hello socket".getBytes());out.flush();read(input);out.close();}public static void read(InputStream input) throws IOException {byte[] buf = new byte[128];int size = 0;while ((size = input.read(buf,0,buf.length)) != -1) {System.out.print(new String(buf));}}
}服务端:
public class SocketServer {public static void main(String[] args) {SocketServer ss = new SocketServer();int port = 8888;try {ss.startServer(port);} catch (Exception e) {e.printStackTrace();}}public void startServer(int port) throws Exception {ServerSocket serverSocket = new ServerSocket(port);Socket server = null;try {while (true) {server = serverSocket.accept();System.out.println("server socket is start……");try {BufferedReader input = new BufferedReader(new InputStreamReader(new ByteArrayInputStream("服务端发给客户端的信息".getBytes())));BufferedInputStream in = new BufferedInputStream(server.getInputStream());PrintWriter out = newPrintWriter(newOutputStreamWriter(server.getOutputStream()));String clientstring = null;out.println("欢迎客户端连入");out.flush();byte[] buf = new byte[128];int size = 0;while (( size = in.read(buf,0,buf.length)) != -1) {System.out.println(new String(buf));}out.print(" client is over");out.flush();out.close();System.out.println(" client is over");} catch (Exception e) {e.printStackTrace();} finally {server.close();}}} catch (Exception e) {e.printStackTrace();} finally {serverSocket.close();}}}
这段代码执行以后会发现server类 read()方法发生了阻塞,经过查找资料发现 read() 是一个阻塞函数,如果客户端没有声明断开outputStream那么它就会认为客户端仍旧可能发送数据,像read()这种阻塞读取函数还有BufferedReader类种的 readLine()、DataInputStream种的readUTF()等。
2. 解决方案
1)Socket任意一端在调用完write()方法时调用shutdownOutput()方法关闭输出流,这样对端的inputStream上的read操作就会返回-1, 这里我们要注意下不能调用socket.getInputStream().close()。因为它会导致socket直接被关闭。 当然如果不需要继续在socket上进行读操作,也可以直接关闭socket。但是这个方法不能用于通信双方需要多次交互的情况。
out.write("sender say hello socket".getBytes());
out.flush();
client.shutdownOutput(); //调用shutdown 通知对端请求完毕
这个解决方案缺点非常明显,socket任意一端都依赖于对方调用shutdownOutput()来完成read返回 -1,如果任意一方没有执行shutdown函数那么就会出现问题。所以一般我们都会在socket请求时设置连接的超时时间 socket.setSoTimeout(5000);以防止长时间没有响应造成系统瘫痪。
while (true) {server = serverSocket.accept();System.out.println("server socket is start……");server.setSoTimeout(5000);.....}
2)发送数据时,约定数据的首部固定字节数为数据长度。这样读取到这个长度的数据后,就不继续调用read方法
这种方式优点是不依赖对方调用shutdown函数,响应较快,缺点是数据传输是最大字节数固定,需双方事先约定好长度,伸缩性差。
3)发送数据时,约定前几位返回数据byte[]长度大小或最后输出 \n 或 \r 作为数据传输终止符。
客户端out.write("sender say hello socket \n".getBytes());out.flush();服务器端byte[] buf = new byte[1];int size = 0;StringBuffer sb = new StringBuffer();while (( size = in.read(buf,0,buf.length)) != -1) {String str = new String(buf);if(str.equals("\n")) {break;}sb.append(str);System.out.print(str);}
这种方式是对第二种方案的改良版,但不得不说 这是目前socket数据传输的最常用处理read()阻塞的解决方案。
read方法阻塞的解决相关推荐
- java无阻塞执行脚本,JAVA调用Shell脚本-及阻塞的解决方法
JAVA调用Shell脚本--及阻塞的解决办法 用java调用shell,使用 Process p=Runtime.getRuntime().exec(String[] cmd); Runtime.e ...
- 在ML中缺乏数据可是个大问题,亲测有效的5种方法帮您解决
https://www.toutiao.com/a6701193162699833859/ 在我做过的很多项目中,公司虽然有非常棒的AI商业创意,但当他们意识到自己没有足够的数据时,却会慢慢的变得沮丧 ...
- cocos2d-js中listView的jumpToBottom()方法无效的解决方法
cocos2d-js中listView的jumpToBottom()方法无效的解决方法 参考文章: (1)cocos2d-js中listView的jumpToBottom()方法无效的解决方法 (2) ...
- 基于PLSQL的数据库备份方法及如何解决导出clob和blob类型数据报错的问题
基于PLSQL的数据库备份方法及如何解决导出clob和blob类型数据报错的问题 参考文章: (1)基于PLSQL的数据库备份方法及如何解决导出clob和blob类型数据报错的问题 (2)https: ...
- 安装linux修复系统文件夹,误删除 Linux 系统文件了?这个方法教你解决
误删除linux系统文件了?不用急,本文将给你一个恢复linux文件的方法,让你轻松应对运维中的各风险问题.方法总比问题多~ 说在前面的话 针对日常维护操作,难免会出现文件误删除的操作.大家熟知lin ...
- 家里wifi网速越来越慢_家里WIFI越用越卡?教你3个小方法,彻底解决网速慢、不稳定等问题...
相信各位小伙伴都遇到过家里Wi-Fi网络频繁卡顿的现象,当遇到这种情况是大多数人的第一反应就是"有其他人在蹭家里的Wi-Fi",为此便会将自家的Wi-Fi密码改成长串数字+复杂字母 ...
- 电视android怎么解决,安卓手机怎么投屏到电视?用这3种方法可完美解决
安卓手机怎么投屏到电视?用这3种方法可完美解决 2021年04月01日 17:47作者:网络编辑:王动 分享 有些用户觉得智能电视能看的资源太少,想把安卓手机里的资源投屏到电视上看,该怎么办呢?下面简 ...
- linux上ftp和lftp冲突,Linux FTP客户端 Lftp 使用方法,该如何解决
当前位置:我的异常网» Linux/Unix » Linux FTP客户端 Lftp 使用方法,该如何解决 Linux FTP客户端 Lftp 使用方法,该如何解决 www.myexceptions. ...
- 误删除 linux 系统文件了?这个方法教你解决
误删除 linux 系统文件了?这个方法教你解决 参考文章: (1)误删除 linux 系统文件了?这个方法教你解决 (2)https://www.cnblogs.com/cheyunhua/p/10 ...
最新文章
- Spring Boot 2.0官方文档之 Actuator
- 2021暑假实习-SSM超市积分管理系统-day06笔记
- 【软件使用】Windows下的Objective-C集成开发环境搭建(IDE)
- 设计费收费标准2002修订_@设计师,2019景观园林设计收费标准,注意查收!
- 吴恩达深度学习编程作业汇总
- 一次900万+数据量的 SQL 查询优化分析【上百倍性能优化】
- python人脸识别教程_50行Python代码+OpenCV实现人脸识别!史上最详细的教程!
- Asp.Net MVC2 控件开发实例(2)
- 两个矩阵是否相交的算法_个性化推荐召回算法——Personal Rank
- 设置Tomcat编码格式
- 2021年2月20日 星期六 初九 霾
- 基础数学(八)——期末考试复习
- python报错就一定是有错吗_Python-什么是错误的幻数错误?
- 向日葵 服务器连接失败怎么办
- 票房突破9亿,翻拍片《误杀》凭什么收获票房口碑双丰收?
- P16-Windows与网络基础-本地安全策略
- Ceph新长支持稳定版本Luminous(12.x.x)新功能总结
- 条码打印机碳带装反了会怎么样
- vs2019无法连接到远程服务器,VS2019无法添加引用问题
- Linux 启用端口