Socket 编程中,TCP 流的结束标志与粘包问题
2024-09-29 08:31:32
因为 TCP 本身是无边界的协议,因此它并没有结束标志,也无法分包。
socket和文件不一样,从文件中读,读到末尾就到达流的结尾了,所以会返回-1或null,循环结束,但是socket是连接两个主机的桥梁,一端无法知道另一端到底还有没有数据要传输。
socket如果不关闭的话,read之类的阻塞函数会一直等待它发送数据,就是所谓的阻塞。
如果发送的东西非常多必须要用循环读,可以有以下解决方案:
- 调用socket的 shutdownOutput 方法(Java)关闭输出流,该方法的文档说明为,将此套接字的输出流置于“流的末尾”,这样另一端的输入流上的read操作就会返回-1。
- 约定结束标志,当读到该结束标志时退出不再read。 (Http 的 Transfer-Encoding: Chunked 首部,表示将以一个 length 为 0 的 chunk 做结束标志)
- 设置超时(timeout),会在设置的超时时间到达后抛出SocketTimeoutException异常而不再阻塞。
- 双方定义好通信协议,在协议头部约定好数据的长度。当读取到的长度等于这个长度时就不再继续调用read方法。(Http 的 content-length 首部,会给出主体的长度)
而如果需要发送多个相互独立的内容,内容之间就需要有明确的分界,方法有:
- 像 multipart-form 一样,使用 boundary 字串做分割,使用 Content-Type 等首部做内容标识。
- 用二进制帧做分割,在帧首部定义好帧的长度和其他信息。
参考
关于java网络编程中获取输入流中数据的问题
Linux编程之socket:tcp流协议产生的粘包问题及解决方法
终端如何与服务器通信——玩转通信协议(源码下载)
最新文章
- codevs 1228 苹果树 树链剖分讲解
- docker 常用命令(*)
- C语言连接SQLSERVER数据库
- cf 700 A As Fast As Possible
- 【RoR win32】新建rails项目找不到script/server的解决办法
- 解决一台机器同时运行多个Tomcat服务
- iOS UILabel自定义行间距时获取高度
- HBase Java API使用(一)
- BZOJ1640: [Usaco2007 Nov]Best Cow Line 队列变换
- hdu5976贪心乘法逆元
- [array] leetcode - 40. Combination Sum II - Medium
- python之路--day10-闭包函数
- Dubbo配置引发的一个问题--- Duplicate spring bean id
- gunicorn+anaconda+nginx部署django项目(ubuntu)
- node处理表单文件,获取formdata的数据
- JavaScript之获取表格目标数据(TableDom.getTableData())
- MySQL 5.7基于GTID复制的常见问题和修复步骤(二)
- LeetCode 429 N-ary Tree Level Order Traversal 解题报告
- git 远程仓库与本地项目关联
- Pipeline 与 xargs