今天开发一个Socket通讯agent,Java 程序中启动一个ServerSocket,用来与shell脚本中"nc"命令通讯并交换数据.ServerSocket可以收到"nc"发送的数据,但是"nc"却接受不到数据..代码样例:
try { InputStreamReader reader = new InputStreamReader(innerSocket.getInputStream()); StringBuffer sb = new StringBuffer(); while (true) { int _c = reader.read(); if (_c == -1) { break; } sb.append((char) _c); } String data = StringUtils.trim(sb.toString()); //如果数据异常 if (StringUtils.isBlank(data)) { return; } BufferedWriter out = new BufferedWriter(new OutputStreamWriter(innerSocket.getOutputStream())); out.write(">>>" + data); out.newLine(); //out.flush();//++++important } } catch (Exception e) { log.error(e); }finally { try{ innerSocket.close(); }catch (Exception e){ // } } }
shell调用方式:
>echo ping | nc 127.0.0.1 10101
代码非常简单, 可是为什么不行呢?通过跟踪,Java代码中可以从socket中read到"ping"字符串,但是为什么out.write(">>>")的数据不能被shell获取呢??OK,换一下代码风格,再试一试:
OutputStream out = innerSocket.getOutputStream(); String back = ">>>" + data; out.write(back.getBytes()); ...
不好意思,成功了...为什么BufferedWriter不行,反而OutStream行呢?后来简单的翻阅了一下源码,简单的修改一下即可:
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(innerSocket.getOutputStream())); out.write(">>>" + data); out.newLine(); out.flush();
加上"out.flush()"即可,对于BufferedWriter而言,write()方法并没有直接将数据写入到物理的IO流中,而是首先cache在了一个字节数组中,只有当cache的数据量达到buffer-size时才会触发flush,flush的作用就是将多个字节依次写入到IO中,原以为socket.close()方法会执行flush(),尽管OutputStream中有flush方法,事实上没有执行.
- public BufferedWriter(Writer out, int bufferSize)
所以使用BufferedWriter的时候,一定要在IO关闭之前,调用flush()方法,否则将会丢失部分数据...真是费劲.
不过顺便还要提一个问题,如果JAVA Socket向远端write数据后,却始终收不到远端发来的数据,还可能有下面的一种情况:
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); writer.write("success 1123"); writer.flush(); //socket.shutdownOutput(); InputStreamReader reader = new InputStreamReader(socket.getInputStream()); StringBuffer sb = new StringBuffer(); while(true){ int _c = reader.read(); if(_c == -1){ break; } sb.append((char)_c); } System.out.println(">>>>read:" + sb.toString()); socket.close();
上面的代码中,socket向远端write数据之后,开始read远端返回的数据,但是始终无法read到数据,是怎么回事?其实原因也很简单,这就是典型的"Socket死锁": socket write()时,同时远端也在read,因为socket通讯是基于流(frame)的,如果远端read时没有收到EOF,那么read操作将一直阻塞,直到socket关闭.上面的代码,就是出现了远端socket read一直阻塞而没有机会执行write,同时本地socket也因为read阻塞,导致了"死锁",代码调整如下:
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); writer.write("success 1123"); writer.flush(); socket.shutdownOutput(); ...
在writer数据结束后,执行shutdownOutput,将output流通道关闭,此时远端socket就会read到EOF, 认为通道中不会再有数据可读.shutdownOutput()方法不会关闭整个socket,只是关闭了socket中的outputStream,不过一旦调用了此方法,此后将不能再调用writer.write()方法.
此外还可以通过socket IO字节成帧手段来解决上述问题.
相关推荐
字符缓冲流Bufferd,直接粘贴到eclipse或者cmd运行即可
goredisgolang redis client, bufferd connection, connection pool, support all redis commands,欢迎大家批评指正,更欢迎大家加入进来。Create a new conn? c, e := Dial("127.0.0.1:6379", pwd, CTimeout, ...
核心飞行系统:框架:核心飞行执行器 该存储库包含NASA的Core Flight Executive(cFE),它是Core Flight System的框架组件。 这是服务和相关框架的集合... 重构SB缓冲区描述符对象CFE_SB_BufferD_t并简化零复制缓冲区
根据提供的标题、描述以及部分文件内容,我们可以提炼出与CCNP(Cisco Certified Network Professional)相关的多个关键知识点。以下是对这些知识点的详细解析: ### CCNP培训资料中的关键技术命令 #### 1. `show ...
那些年,与你同分同位次的同学都去了哪里?全国各大学在四川2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
麒麟win10双系统重新安装win10后麒麟启动菜单看不到解决方法
多邻国Duolingo v6.0.3 高级版.apk
QT网络编程: 实现TCP通讯设置(客户端)
减少重复造轮子,开源微信小程序商城(前后端开源:uniapp+Java)。快速搭建一个属于自己的微信小程序商城。
彩虹云商城 最新彩虹代刷V6.9.0免授权纯净完整版 直接上传源码解压缩后访问域名安装即可,亲测可用 彩虹自助下单系统 安装说明: 上传到空间后直接访问即可根据提示安装。 PHP推荐使用7.0及以上版本 V6.9 1.修复SQL注入漏洞 2.修复后台微信QQ扫码登录 V6.8.5 1.修复亿乐对接 2.新增支持倍数输入框 V6.8 1.更新全新的faka模板 2.新增微信快捷登录 3.新增批量下单功能 4.防CC配置新增滑动验证码模式 5.修复部分地区后台加载错误 6.修复https网站对接http支付接口 7.后台登录支持微信QQ扫码登录
MyBatis-Plus学习思维导图
那些年,与你同分同位次的同学都去了哪里?全国各大学在四川2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
那些年,与你同分同位次的同学都去了哪里?全国各大学在四川2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
分布式搜索引擎ElasticSearch思维导图
网鼎杯
网络安全入门教程(工具版)
科普里控制器调试软件工具使用 win64环境安装
内容概要:本文档详细介绍了GC9503V单片机a-Si TFT LCD驱动器的技术规格,包括主要特点、内部结构图、引脚定义以及系统接口等。GC9503V支持480x864分辨率,16.7百万色显示,无内置GRAM。文章还提供了详细的引脚尺寸、对齐标记尺寸、芯片信息以及接口模式控制的序列实例,如DCS写入命令及其参数。 适合人群:LCD显示屏设计人员、嵌入式系统工程师、电子硬件开发者和技术研究人员。 使用场景及目标:帮助开发者快速理解和应用GC9503V在实际产品中的具体使用方法,掌握LCM与MCU之间的数据交互方式,实现高效的屏幕驱动设计。 其他说明:GalaxyCore公司保留在不事先通知的情况下更改文档内容的权利。
那些年,与你同分同位次的同学都去了哪里?全国各大学在四川2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
yolo系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值