因为 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 首部,会给出主体的长度)

而如果需要发送多个相互独立的内容,内容之间就需要有明确的分界,方法有:

  1. 像 multipart-form 一样,使用 boundary 字串做分割,使用 Content-Type 等首部做内容标识。
  2. 用二进制帧做分割,在帧首部定义好帧的长度和其他信息。

参考

关于java网络编程中获取输入流中数据的问题
Linux编程之socket:tcp流协议产生的粘包问题及解决方法
终端如何与服务器通信——玩转通信协议(源码下载)

最新文章

  1. codevs 1228 苹果树 树链剖分讲解
  2. docker 常用命令(*)
  3. C语言连接SQLSERVER数据库
  4. cf 700 A As Fast As Possible
  5. 【RoR win32】新建rails项目找不到script/server的解决办法
  6. 解决一台机器同时运行多个Tomcat服务
  7. iOS UILabel自定义行间距时获取高度
  8. HBase Java API使用(一)
  9. BZOJ1640: [Usaco2007 Nov]Best Cow Line 队列变换
  10. hdu5976贪心乘法逆元
  11. [array] leetcode - 40. Combination Sum II - Medium
  12. python之路--day10-闭包函数
  13. Dubbo配置引发的一个问题--- Duplicate spring bean id
  14. gunicorn+anaconda+nginx部署django项目(ubuntu)
  15. node处理表单文件,获取formdata的数据
  16. JavaScript之获取表格目标数据(TableDom.getTableData())
  17. MySQL 5.7基于GTID复制的常见问题和修复步骤(二)
  18. LeetCode 429 N-ary Tree Level Order Traversal 解题报告
  19. git 远程仓库与本地项目关联
  20. Pipeline 与 xargs

热门文章

  1. ubuntu openstack windows 镜像制作
  2. 9 Palindrome_Number
  3. 面试中常见的 MySQL 考察难点和热点
  4. IIS6.0开启gzip压缩
  5. python_12_continue
  6. bootstrap table加载数据
  7. CUDA 中dim3含义
  8. java基础编程—统计二进制数中1的个数
  9. 问题005:如何配置JDK,Java运行环境?
  10. Java - 静态方法不具有多态性