因为 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流协议产生的粘包问题及解决方法
终端如何与服务器通信——玩转通信协议(源码下载)

Socket 编程中,TCP 流的结束标志与粘包问题的更多相关文章

  1. UNIX网络编程——tcp流协议产生的粘包问题和解决方案

    我们在前面曾经说过,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体 ...

  2. tcp流协议产生的粘包问题和解决方案

    我们在前面曾经说过,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体 ...

  3. socket编程中客户端常用函数

    1 常用函数 1.1   connect() int connect(int sockfd, const struct sockaddr *servaddr, socklen_taddrlen); 客 ...

  4. 计算机网络(十三),Socket编程实现TCP和UDP

    十三.Socket编程实现TCP和UDP 1.TCP (1)TCPServer.java类 package com.interview.javabasic.socket; import com.int ...

  5. socket编程中write、read和send、recv之间的区别~转载

    socket编程中write.read和send.recv之间的区别   http://blog.csdn.net/petershina/article/details/7946615 一旦,我们建立 ...

  6. PHP socket 编程中的超时设置

    PHP socket 编程中的超时设置.网上找了半天也没找到.贴出来分享之:设置$socket 发送超时1秒,接收超时3秒: $socket = socket_create(AF_INET,SOCK_ ...

  7. Linux socket 编程中存在的五个隐患

    前言:         Socket API 是网络应用程序开发中实际应用的标准 API.尽管该 API 简单,但是   开发新手可能会经历一些常见的问题.本文识别一些最常见的隐患并向您显示如何避免它 ...

  8. python网络编程socket编程(TCP、UDP客户端服务器)

    摘录 python核心编程 使用socket()模块函数创建套接字——通信端点 >>> from socket import * >>> tcpSock = soc ...

  9. [转]SOCKET通信中TCP、UDP数据包大小的确定

    TCP.UDP数据包大小的确定 UDP和TCP协议利用端口号实现多项应用同时发送和接收数据.数据通过源端口发送出去,通过目标端口接收.有的网络应用只能使用预留或注册的静态端口:而另外一些网络应用则可以 ...

随机推荐

  1. LeetCode Add Two Numbers 两个数相加

    /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode ...

  2. C++中调用Python脚本(转载)

    转载▼ 标签: 杂谈 C++中调用Python脚本的意义就不讲了,至少你可以把它当成文本形式的动态链接库,需要的时候还可以改一改,只要不改变接口, C++的程序一旦编译好了,再改就没那么方便了先看Py ...

  3. 新建framework的bundle资源 图片资源被编译成了ttf后缀 解決

    设置combine_hidpi_images为no

  4. IOS 获取手机的屏幕宽度

    //屏幕的宽度 CGFloat screenW=[UIScreen mainScreen].bounds.size.width;

  5. POJ-1274 The Perfect Stall---二分图模板

    题目链接: https://vjudge.net/problem/POJ-1274 题目大意: 有n个奶牛和m个谷仓,现在每个奶牛有自己喜欢去的谷仓,并且它们只会去自己喜欢的谷仓吃东西,问最多有多少奶 ...

  6. 【BZOJ2243】[SDOI2011] 染色(树链剖分)

    点此看题面 大致题意: 有一棵\(n\)个节点的无根树和\(m\)个操作,且每个节点有一个颜色.操作有两种:一种是将两点树上路径之间所有点染成颜色\(c\),另一种是询问两点树上路径之间颜色段的数量. ...

  7. kubernetes-ingress(十)

    ingress https://kubernetes.io/docs/concepts/services-networking/ingress/ pod与ingress的关系 •通过label-sel ...

  8. [转] 防止js全局变量污染方法总结

    javaScript 可以随意定义保存所有应用资源的全局变量.但全局变量可以削弱程序灵活性,增大了模块之间的耦合性.在多人协作时,如果定义过多的全局变量 有可能造成全局变量冲突,也就是全局变量污染问题 ...

  9. Python02 变量

    变量 因为Python是弱变量类型编程语言,所以变量赋值不需要类型声明. 每个变量在内存中创建,都包括变量的标识,名称和数据这些信息. 每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建. 变量 ...

  10. java定义一个Circle类,包含一个double型的radius属性代表圆的半径,一个findArea()方法返回圆的面积

    需求如下:(1)定义一个Circle类,包含一个double型的radius属性代表圆的半径,一个findArea()方法返回圆的面积. (2)定义一个类PassObject,在类中定义一个方法pri ...