计算机网络 TCP粘包问题

什么是粘包?

粘包是指的是数据和数据之间没有没有明确的分界线,导致不能够正确的传输数据(只有TCP会粘包 UDP 永远不会粘包),粘包问题只针对于一切字节流的协议。

TCP也可以称为流式协议,UDP称为数据报式协议。

对于流式协议:发送端可以1K1K的发送数据,接收端可以2k2k的提取数据,也可以3K4K的提取数据,所以对于接收端应用程序中看到的数据就是一个整体,“数据流”,一条消息里面有多少字节应用程序是看不见的,所以TCP协议面向字节流,就会出现粘包问题,而UDP这种面向消息的协议,每个UDP段都是一条消息,接收方必须以消息为单位进行提取数据,不能一次提取任意字节的数据所谓的粘包问题就是接收方不知道消息和消息之间的边界,不知道一次提取多少个字节导致的。

粘包问题出现的具体原因

应用程序无法直接操作硬件,应用程序想要操作数据必须要将数据交给操作系统,OS会为应用提供数据传输的服务,所以OS不会立刻把数据发出去,会为应用程序提供一个缓冲区,存储临时的数据,这些数据存在一起就无法区分边界了。

发送方:当应用程序调用send函数时候,应用程序会将数据从应用程序拷贝到操作系统缓存里面,再由OS从缓冲区里面读数据,把数据发出去。

数据缓冲区的合并:TCP协议为了提高传输效率,可能会在发送数据时将多个数据包合并成一个进行发送,而接收方可能一次性接收到多个数据包。

接收方: 对方计算机收到的数据也是OS先收到的,至于应用程序如何处理这些数据,OS不知道,所以同样需要将数据先存储到OS 的缓冲区里面,当应用程序调用recv的时候,实际上是将OS缓冲区里面的数据拷贝到应用程序的过程。

接收方读取不及时:如果接收方没有及时读取缓冲区中的数据,可能会导致多个数据包被一次性读取,从而形成粘包现象。

粘包问题的解决

1.使用应用层协议(http,https)来封装要传输的不定长的数据包。

2.添加标志位,在每个数据的后面添加一些特殊字符,如果遇到特殊字符,说明这条数据接收完毕了 每接收一个字符就要对这些字符进行判定,判定是不是特殊的字符串,效率很低。

3.在发送数据快之前,在数据块之前添加一个固定大小的包头:数据头+数据块 数据头:存储当前数据包的总字节数,接收端先接收数据头,然后再根据数据头接收对应的大小 数据块:当前数据包的内容。

//例子:
struct Node n1;
int nSize = sizeof(n1);
//发送
send(sockClient,(char*)&nSize, sizeof(int),0); //先发包大小
send(sockClient,(char*)&n1, sizeof(n1),0);//发数据包
//接收 
int nPackSize = 0;
recv(sockClient,(char*)&nPackSize, sizeof(int),0);//先接收包大小
char* buf = new char[nPackSize]:
recv(sockClient, buf,nPackSize, 0);//再接收包,delete[] buf;

4.固定包大小,固定每个包的大小,但这样会造成资源浪费。

5.短连接,每次连接发一个包就断开重连再发,适合长时间短交流。

 

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值