TCPIP / 粘包和拆包的定义以及解决办法

一、粘包

1、定义

指发送方发送的若干数据包在接收方接收时粘成一团,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。

2、产生的原因

(1)发送方的原因

TCP默认使用 Nagle 算法,而 Nagle 算法主要做如下两件事情:

  • 只有上一个分组得到确认,才发送下一个分组。
  • 收集多个小分组,在一个确认到来时一起发送。

Nagle 算法造成了发送方可能存在粘包现象。

(2)接收端的原因

接收端接收到分组时,应用层并不会立即处理,接收端将接收到的分组放到接收缓存中,然后应用程序主动从接收缓存中读取分组,当接收端接收分组的速度大于应用程序读取分组的速度时,多个包就会被存至缓存。应用程序读取时,就会读到多个首尾相连在一起的包。

3、什么时候需要处理 TCP 粘包问题。

  • 如果发送方的多个分组本来就是同一个数据的不同部分,比如一个很大的文件分成多个分组发送,这时不需要处理TCP粘包问题。
  • 如果多个分组毫不相干,甚至是并联关系,则一定要处理TCP粘包问题。

二、拆包

1、定义

发送方将一个数据包拆分成了多个数据包进行传送。

2、产生的原因

  • 要发送的数据大于 TCP 剩余缓冲区的大小。
  • 要发送的数据大于 MSS 最大报文长度。

三、如何处理TCP粘包和TCP拆包问题

无论是TCP拆包还是TCP粘包本质问题都在于无法区分包的界限,可以采用以下三种方式来区分包的界限

  1. 消息数据固定长度,但是浪费存储和网络资源。
  2. 使用分割符来区分包的界限。
  3. 数据包的头部中增加数据包长度字段。

四、代码示栗

#pragma pack(1)

struct XMNPkgHeader
{
    // 报文的总长度(包头 + 包体)。
    unsigned short pkglen;

    // 消息类型的代码,用于区别不同的命令(消息)。
    unsigned short msgcode;

    // CRC32 校验,用于防止接收到的数据和 client 发送的数据不符的问题。
    int crc32;
};

#pragma pack()

之所以使用 pack(1) ,目的是让包头大小更紧凑,节约流量。 由于包头的大小(headerlen)是固定的,通过 pkglen 就可以知道包体的大小(bodylen = pkglen - headerlen)。

在已知包头和包体的长度的情况下,接受数据包的时候,首先可以接收 headerlen 大小的数据,如果接收的数据不够,则下次接收包头剩余的数据,直至包头数据接收完毕。

包头数据接收完毕之后,再接收 bodylen 大小的数据,如果接收的数据不足,则接收剩下的包体的数据,直至包体的数据接收完毕。

五、总结

TCP 之所以存在拆包和粘包问题,本质就是 TCP 是面向字节流的,而 UDP 是面向报文的!

六、源码链接

https://github.com/xuchanglong/XMoon

 

(SAW:Game Over!)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: TCP/IP堆栈是一种网络通信协议栈,它是建立在Internet协议套件基础上的一种通信协议集合。它由一系列层次化的协议组成,用于在计算机网络中进行数据传输和通信。 其中,tcpip.h是一个与TCP/IP堆栈相关的头文件,它包含了一些与TCP/IP协议有关的常量、数据结构、函数和宏定义等,用于支持应用程序与底层协议之间的交互。 在使用TCP/IP堆栈进行网络通信时,应用程序可以通过包含tcpip.h头文件来获取一些必要的信息和功能。tcpip.h中定义的常量可以用来指定网络协议的类型或操作的选项,数据结构可以存储和传递协议相关的数据,函数可以用于发送、接收、连接和管理网络数据,宏定义可以简化程序开发过程中的处理。 通过tcpip.h头文件,应用程序可以与TCP/IP堆栈进行交互,实现网络通信和数据传输。通过使用包含在tcpip.h中的相关功能和数据结构,应用程序可以灵活地控制数据的发送和接收,创建和管理网络连接,实现各种应用需求。 总而言之,tcpip.h是一个与TCP/IP堆栈相关的头文件,它提供了一些必要的信息、功能和数据结构,用于应用程序与底层协议之间的交互,实现网络通信和数据传输。它在网络开发中起到了重要的作用。 ### 回答2: TCP/IP是一种通信协议栈,是网络通信的基础。tcpip.h 是TCP/IP协议栈的头文件,它包含了TCP/IP协议栈中定义的各种函数、结构体和宏定义TCP/IP协议栈是一组网络协议的集合,用于在互联网上进行数据通信。它包括四个主要的协议层:网络接口层、网络层、传输层和应用层。这些协议层分别负责处理物理连接、数据包路由、可靠传输和应用程序交互等功能。 tcpip.h 是TCP/IP协议栈的头文件,它定义了各个层次的函数、结构体和宏定义,以及协议栈的相关操作。有了这个头文件,开发人员可以更方便地使用TCP/IP协议栈提供的各种功能。 在使用 tcpip.h 头文件时,开发人员可以利用其中的函数实现网络连接的建立、数据的传输和处理、错误的处理等操作。同时,它还定义了各种数据结构和宏定义,用于组织和处理网络数据。 总之,tcpip.h 是TCP/IP协议栈的头文件,它提供了使用TCP/IP协议栈进行网络通信的必要接口和定义。它的存在使得开发人员可以更加方便地使用TCP/IP协议栈,实现各种网络通信功能,从而构建起稳定可靠的互联网通信环境。 ### 回答3: TCP/IP协议栈是一种网络协议栈,用于在网络通信中实现数据传输和通信功能。而tcpip.h是TCP/IP协议栈头文件之一,用于定义TCP/IP协议栈中各种数据结构、常量和函数的声明。 在tcpip.h文件中,我们可以找到一些常见的数据结构,如TCP头部(tcp_header)和IP头部(ip_header)等。这些数据结构定义了相应协议包的格式,方便了网络通信中数据包的解析和处理。 此外,tcpip.h文件中还包含了一些常量的定义,如网络协议的版本号和一些特定的协议号等。这些常量的定义使得我们能够在程序中使用这些常量,更加方便地进行网络通信相关操作。 另外,tcpip.h文件还包含了很多函数的声明,这些函数是用于处理TCP/IP协议栈中的各种操作,例如建立TCP连接、发送和接收数据等。通过调用这些函数,我们可以直接使用TCP/IP协议栈提供的功能来实现网络通信。 总之,TCP/IP协议栈是在网络通信中起关键作用的协议栈,而tcpip.h则是其中的头文件之一,通过定义数据结构、常量和函数的声明,方便了网络通信相关操作的实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值