转载自别人的博客

  1. 在网络编程中,读取数据时遇到了该问题:服务器端运行到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方法阻塞的解决相关推荐

  1. java无阻塞执行脚本,JAVA调用Shell脚本-及阻塞的解决方法

    JAVA调用Shell脚本--及阻塞的解决办法 用java调用shell,使用 Process p=Runtime.getRuntime().exec(String[] cmd); Runtime.e ...

  2. 在ML中缺乏数据可是个大问题,亲测有效的5种方法帮您解决

    https://www.toutiao.com/a6701193162699833859/ 在我做过的很多项目中,公司虽然有非常棒的AI商业创意,但当他们意识到自己没有足够的数据时,却会慢慢的变得沮丧 ...

  3. cocos2d-js中listView的jumpToBottom()方法无效的解决方法

    cocos2d-js中listView的jumpToBottom()方法无效的解决方法 参考文章: (1)cocos2d-js中listView的jumpToBottom()方法无效的解决方法 (2) ...

  4. 基于PLSQL的数据库备份方法及如何解决导出clob和blob类型数据报错的问题

    基于PLSQL的数据库备份方法及如何解决导出clob和blob类型数据报错的问题 参考文章: (1)基于PLSQL的数据库备份方法及如何解决导出clob和blob类型数据报错的问题 (2)https: ...

  5. 安装linux修复系统文件夹,误删除 Linux 系统文件了?这个方法教你解决

    误删除linux系统文件了?不用急,本文将给你一个恢复linux文件的方法,让你轻松应对运维中的各风险问题.方法总比问题多~ 说在前面的话 针对日常维护操作,难免会出现文件误删除的操作.大家熟知lin ...

  6. 家里wifi网速越来越慢_家里WIFI越用越卡?教你3个小方法,彻底解决网速慢、不稳定等问题...

    相信各位小伙伴都遇到过家里Wi-Fi网络频繁卡顿的现象,当遇到这种情况是大多数人的第一反应就是"有其他人在蹭家里的Wi-Fi",为此便会将自家的Wi-Fi密码改成长串数字+复杂字母 ...

  7. 电视android怎么解决,安卓手机怎么投屏到电视?用这3种方法可完美解决

    安卓手机怎么投屏到电视?用这3种方法可完美解决 2021年04月01日 17:47作者:网络编辑:王动 分享 有些用户觉得智能电视能看的资源太少,想把安卓手机里的资源投屏到电视上看,该怎么办呢?下面简 ...

  8. linux上ftp和lftp冲突,Linux FTP客户端 Lftp 使用方法,该如何解决

    当前位置:我的异常网» Linux/Unix » Linux FTP客户端 Lftp 使用方法,该如何解决 Linux FTP客户端 Lftp 使用方法,该如何解决 www.myexceptions. ...

  9. 误删除 linux 系统文件了?这个方法教你解决

    误删除 linux 系统文件了?这个方法教你解决 参考文章: (1)误删除 linux 系统文件了?这个方法教你解决 (2)https://www.cnblogs.com/cheyunhua/p/10 ...

最新文章

  1. Spring Boot 2.0官方文档之 Actuator
  2. 2021暑假实习-SSM超市积分管理系统-day06笔记
  3. 【软件使用】Windows下的Objective-C集成开发环境搭建(IDE)
  4. 设计费收费标准2002修订_@设计师,2019景观园林设计收费标准,注意查收!
  5. 吴恩达深度学习编程作业汇总
  6. 一次900万+数据量的 SQL 查询优化分析【上百倍性能优化】
  7. python人脸识别教程_50行Python代码+OpenCV实现人脸识别!史上最详细的教程!
  8. Asp.Net MVC2 控件开发实例(2)
  9. 两个矩阵是否相交的算法_个性化推荐召回算法——Personal Rank
  10. 设置Tomcat编码格式
  11. 2021年2月20日 星期六 初九 霾
  12. 基础数学(八)——期末考试复习
  13. python报错就一定是有错吗_Python-什么是错误的幻数错误?
  14. 向日葵 服务器连接失败怎么办
  15. 票房突破9亿,翻拍片《误杀》凭什么收获票房口碑双丰收?
  16. P16-Windows与网络基础-本地安全策略
  17. Ceph新长支持稳定版本Luminous(12.x.x)新功能总结
  18. 条码打印机碳带装反了会怎么样
  19. vs2019无法连接到远程服务器,VS2019无法添加引用问题
  20. Linux 启用端口

热门文章

  1. 【word】分节符的作用
  2. 那些长期喝咖啡的人,现在都怎么样了?
  3. STL rotate旋转算法
  4. Android 接入Facebook实现第三方登陆教程(精简版)
  5. Linux字符界面与图形界面的切换
  6. 达摩院发布2023十大科技趋势,多领域“日进一寸”式融合创新
  7. String Matching 字符串匹配算法——干货从头放到尾
  8. SCI:SCI论文写作技巧的详细攻略
  9. 《怪诞行为学二》启发(一)
  10. matlab psb,基于Matlab_PSB的电路仿真分析