MTU: Maxitum Transmission Unit 最大传输单元
MSS: Maxitum Segment Size 最大分段大小
由于以太网EthernetII最大的数据帧是1518Bytes这样,刨去以太网帧的帧头(DMAC目的地址MAC48bit=6Bytes+SMAC源MAC地址48bit=6Bytes+Type域2bytes)14Bytes和帧尾CRC校验部分4Bytes(这个部门有时候大家也把它叫做FCS),那么剩下承载上层协议的地方也就是Data域最大就只能有1500Bytes. 这个值我们就把它称之为MTU。
以太网的MTU是1500,再减去PPP的包头包尾的开销(8Bytes),就变成1492。
MSS就是TCP数据包每次能够传输的最大数据分段。为了达到最佳的传输效能,TCP协议在建立连接的时候通常要协商双方的MSS值,这个值TCP协议在实现的时候往往用MTU值代替(需要减去IP数据包包头的大小20Bytes和TCP数据段的包头20Bytes)所以往往MSS为1460。通讯双方会根据双方提供的MSS值得最小值确定为这次连接的最大MSS值。
在前面的文章中, 我们讨论了IP的包格式, 也说过TCP/UDP的包格式。 无论是TCP还是UDP, 最终还是封装成了IP包, 我们知道, IP包的最大程度为65535个字节, 于是很多初学者会误解, 以为这65535字节的IP包数据, 是直接被数据链路层套上帧头和帧尾巴的。 比如, 下图就容易让人产生一个极大的误解:
这幅图的最大误人子弟之处在于, 如果上层数据比较长, 是无法套在一个tcp头部之后的, 其他各层也有类似特点。 举个本文涉及到的例子, 网络层的数据如果过长, 是没法直接加载链路层上的, 需要将网络层的数据分片, 然后在数据链路层组装成多个帧(而不是一个)。
下面, 我们来看看数据链路层(用以太网来举例)对上一层数据(网络层数据)长度的限制:
可以看到, 在单个帧中, IP数据包必须小于1500字节, 这个1500就是MTU(max transmission unit)能达到的最大值, 它是数据链路层允许的最大IP包。
回想下以前说的概念:
UDP包头中, UDP整个包的最大长度是65535个字节, 但是IP数据包的最大值也是这个长度, 所以IP层允许的最大UDP包长绝对不能65535个字节(而应该是65535 - 20个字节)。 同理, IP包的最大长度是65535个字节, 但是数据链路层允许的最大IP包, 绝对不能是65535个自己, 实际上远远小于这个数(如上图)。
在本文中, 我们了解到, 实际上, MTU的定义就是: 数据链路层允许的最大IP包长(其最大值是1500字节)。 理解这很重要, 在后面的博文中, 我们会继续说到。
有个问题有点拗口, MTU中的M已经有了“最”的意思, 为什么还说MTU的最大值呢? 爱思考的, 可以思考下。 我们后面再说。
我们已经了解到, 数据链路层对上层IP包的长度是有限制的, 以典型的以太网为例, 这个限制值即为MTU(最大值是1500字节), 为此, IP层对上层网络层的数据也有限制, 这个限制值是MSS(最大值为1460字节), 至于为什么是这两个值, 我们在前面的文章已经解释过了, 故不再赘述。
我们设想一下, 如果应用层需要用UDP发送2000字节的数据, 那么加上IP头和UDP头后, 就是2028个字节了, 超过了MTU的限制, 那怎么办呢? 此时, 协议栈在IP层采用了分片的机制, 把大的应用数据拆分成若干个小的数据, 也样就有了若干个IP包, 而且会保证每个IP包不超过1500字节。用图来表示就是:
可以看到, 分成了两个IP包来发送, 且第二个IP包没有UDP数据, 没有端口信息! 这一点十分值得注意。 如果过滤端口来抓包, 肯定抓不到这个IP包。 第一个包也会有点怪异, 其中UDP头中标明的包长度包含而第二个包的应用数据长度。
事实是否真的如此呢? 我们来写程序并抓包验证:
udp服务端的程序为:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int main()
{
struct sockaddr_in srvAddr;
bzero(&srvAddr,sizeof(srvAddr));
srvAddr.sin_family = AF_INET;
srvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
srvAddr.sin_port = htons(8765);
int srvAddrLen = sizeof(srvAddr);
int iSock = socket(AF_INET, SOCK_DGRAM, 0); // udp
bind(iSock, (struct sockaddr *)&srvAddr, sizeof(srvAddr));
while(1)
{
getchar();
char szBuf[50001] = {0};
recvfrom(iSock, szBuf, sizeof(szBuf) - 1, 0, (struct sockaddr *)&srvAddr, (socklen_t*)&srvAddrLen);
printf("msg from client [%s]\n", szBuf);
}
close(iSock);
return 0;
}
udp客户端的程序为:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char *argv[])
{
struct sockaddr_in srvAddr;
bzero(&srvAddr, sizeof(srvAddr));
srvAddr.sin_family = AF_INET;
srvAddr.sin_addr.s_addr = inet_addr("10.100.70.140");
srvAddr.sin_port = htons(8765);
int iSock = socket(AF_INET, SOCK_DGRAM, 0); // udp
#define N 2000
char szBuf[N] = {0};
for(unsigned int i = 0; i < N; i++) //字符数组最后一个字符不要求是‘\0’
{
szBuf[i] = 'a';
}
int iRet = sendto(iSock, szBuf, sizeof(szBuf), 0, (struct sockaddr *)&srvAddr, sizeof(srvAddr));
printf("send size is %d, iRet is %d, errmsg[%s]\n", sizeof(szBuf), iRet, strerror(errno));
close(iSock);
return 0;
}
服务端抓包结果:
00:13:57.187159 IP 10.100.70.139.46671 > 10.100.70.140.ultraseek-http: UDP, length 2000
0x0000: 4500 05dc 0510 2000 4011 ae22 0a64 468b E.......@..".dF.
0x0010: 0a64 468c b64f 223d 07d8 116e 6161 6161 .dF..O"=...naaaa
0x0020: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0030: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0040: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0050: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0060: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0070: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0080: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0090: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00d0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00e0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00f0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0100: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0110: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0120: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0130: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0140: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0150: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0160: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0170: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0180: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0190: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01d0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01e0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01f0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0200: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0210: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0220: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0230: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0240: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0250: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0260: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0270: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0280: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0290: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x02a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x02b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x02c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x02d0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x02e0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x02f0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0300: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0310: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0320: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0330: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0340: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0350: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0360: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0370: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0380: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0390: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x03a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x03b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x03c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x03d0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x03e0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x03f0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0400: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0410: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0420: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0430: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0440: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0450: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0460: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0470: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0480: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0490: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x04a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x04b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x04c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x04d0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x04e0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x04f0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0500: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0510: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0520: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0530: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0540: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0550: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0560: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0570: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0580: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0590: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x05a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x05b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x05c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x05d0: 6161 6161 6161 6161 6161 6161 0000 0000 aaaaaaaaaaaa....
0x05e0: 0000 0000 0000 0000 0000 0000 ............
00:13:57.187161 IP 10.100.70.139 > 10.100.70.140: ip-proto-17
0x0000: 4500 0224 0510 00b9 4011 d121 0a64 468b E..$....@..!.dF.
0x0010: 0a64 468c 6161 6161 6161 6161 6161 6161 .dF.aaaaaaaaaaaa
0x0020: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0030: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0040: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0050: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0060: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0070: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0080: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0090: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00d0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00e0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00f0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0100: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0110: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0120: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0130: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0140: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0150: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0160: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0170: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0180: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0190: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01d0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01e0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01f0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0200: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0210: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0220: 6161 6161 0000 0000 0000 0000 0000 0000 aaaa............
0x0230: 0000 0000 ....
从结果看, 确实分为了两个IP包来发送, 第一个IP包数据的业务数据的长度是1472个字节, 但是, 你看看, 那个length是2000字节呢。 在看第二个IP包, 果然只有IP头(有IP地址), 没有UDP头(没有端口信息)。 幸好, 我们是用过滤IP方式来抓包的, 否则, 如果过滤端口抓包, 第二个包肯定住不到。
注意: IP层的分片, 对于UDP层来说, 是透明的, 无感知的。应用层更是感觉不到, 所以, 你用socket编程, 根本不知道这个东东。
我们再看看TCP, 上面说了, MSS的最大值是1460(不同系统的MSS值可能不一样, 这个值是在三次握手过程的syn包中确定的, 当然, 实际中的业务数据仍然可以小于syn包中约定的 MSS值)
回头看一下, 上面UDP例子中的IP分片实在IP层完成的, 而TCP分段是在TCP层完成的, 如图:
可以看到, TCP层提前完成了分段, 而且, 两个TCP包中都有TCP头, 这是必然的。 所以到了IP层后, 都保留了TCP头, 当然就有了端口信息啊。 这一点与IP层次的分片是不同的。
而且我们应该看到, 因为TCP包在TCP层已经做了限制, 这就决定了, 等TCP包达到IP层的时候, IP层的数据绝对不会超过MTU, 因此, 对于TCP传输来说, IP层是没有必要分片的, 因为TCP层分段的时候, 已经考虑到了这个限制。
所以, 我们经常会说, UDP传输中, IP分片, 是受到了MTU的限制, TCP传输中, TCP分段, 是受到了MSS的限制(实际上最终还是受到了MTU的限制)
事实是否真的如此呢? 我们来写程序并抓包验证:
tcp服务端程序为:
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <malloc.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <fcntl.h>
int main()
{
int sockSrv = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addrSrv;
addrSrv.sin_family = AF_INET;
addrSrv.sin_addr.s_addr = INADDR_ANY;
addrSrv.sin_port = htons(8765);
bind(sockSrv, (const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in));
listen(sockSrv, 5);
struct sockaddr_in addrClient;
int len = sizeof(struct sockaddr_in);
int sockConn = accept(sockSrv, (struct sockaddr *)&addrClient, (socklen_t*)&len);
unsigned int total = 0;
while(1)
{
char szRecvBuf[5001] = {0};
int iRet = recv(sockConn, szRecvBuf, sizeof(szRecvBuf) - 1, 0);
total += iRet;
printf("iRet is %u, total %u\n", iRet, total);
getchar();
}
close(sockConn);
close(sockSrv);
return 0;
}
tcp客户端的程序为:
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <malloc.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <fcntl.h>
int main()
{
int sockClient = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addrSrv;
addrSrv.sin_addr.s_addr = inet_addr("10.100.70.140");
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(8765);
connect(sockClient, ( const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in));
#define N 2000
char szSendBuf[N] = {0};
for(unsigned int i = 0; i < N; i++) //字符数组最后一个字符不要求是‘\0’
{
szSendBuf[i] = 'a';
}
int iRet = send(sockClient, szSendBuf, sizeof(szSendBuf) , 0);
printf("send size is %d, iRet is %d\n", sizeof(szSendBuf), iRet);
getchar();
close(sockClient);
return 0;
}
我们在服务端抓包, 结果为:
19:10:51.214715 IP 10.100.70.139.44840 > 10.100.70.140.ultraseek-http: Flags [.], seq 0:1416, ack 1, win 56, options [nop,nop,TS val 1277047042 ecr 1277045798], length 1416
0x0000: 4500 05bc 41c9 4000 4006 5194 0a64 468b E...A.@.@.Q..dF.
0x0010: 0a64 468c af28 223d fe86 70c6 8488 f6fd .dF..("=..p.....
0x0020: 8010 0038 cc2e 0000 0101 080a 4c1e 3102 ...8........L.1.
0x0030: 4c1e 2c26 6161 6161 6161 6161 6161 6161 L.,&aaaaaaaaaaaa
0x0040: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0050: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0060: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0070: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0080: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0090: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00d0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00e0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00f0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0100: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0110: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0120: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0130: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0140: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0150: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0160: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0170: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0180: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0190: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01d0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01e0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01f0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0200: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0210: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0220: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0230: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0240: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0250: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0260: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0270: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0280: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0290: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x02a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x02b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x02c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x02d0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x02e0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x02f0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0300: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0310: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0320: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0330: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0340: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0350: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0360: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0370: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0380: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0390: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x03a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x03b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x03c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x03d0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x03e0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x03f0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0400: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0410: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0420: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0430: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0440: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0450: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0460: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0470: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0480: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0490: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x04a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x04b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x04c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x04d0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x04e0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x04f0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0500: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0510: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0520: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0530: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0540: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0550: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0560: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0570: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0580: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0590: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x05a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x05b0: 6161 6161 6161 6161 6161 6161 0000 0000 aaaaaaaaaaaa....
0x05c0: 0000 0000 0000 0000 0000 0000 ............
19:10:51.214716 IP 10.100.70.139.44840 > 10.100.70.140.ultraseek-http: Flags [P.], seq 1416:2000, ack 1, win 56, options [nop,nop,TS val 1277047042 ecr 1277045798], length 584
0x0000: 4500 027c 41ca 4000 4006 54d3 0a64 468b E..|A.@.@.T..dF.
0x0010: 0a64 468c af28 223d fe86 764e 8488 f6fd .dF..("=..vN....
0x0020: 8018 0038 081d 0000 0101 080a 4c1e 3102 ...8........L.1.
0x0030: 4c1e 2c26 6161 6161 6161 6161 6161 6161 L.,&aaaaaaaaaaaa
0x0040: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0050: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0060: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0070: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0080: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0090: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00d0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00e0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x00f0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0100: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0110: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0120: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0130: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0140: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0150: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0160: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0170: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0180: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0190: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01a0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01b0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01c0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01d0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01e0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x01f0: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0200: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0210: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0220: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0230: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0240: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0250: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0260: 6161 6161 6161 6161 6161 6161 6161 6161 aaaaaaaaaaaaaaaa
0x0270: 6161 6161 6161 6161 6161 6161 0000 0000 aaaaaaaaaaaa....
0x0280: 0000 0000 0000 0000 0000 0000 ............
可见, 确实分为了两个TCP/IP包来传输, 而且要注意到, 两个IP包, 都是有TCP头的, 甚是让人欣慰。 不过, 根据我们画图分析, 两次预期的业务数据长度应该是1460字节和540字节, 而实际抓包却分别是:1416字节和584字节。 这只是实现不同而已, 在MSS的限制下, 协议栈和系统具体进行怎样的限制, 并无错误, 无可厚非。
注意: TCP层的分段, 对于应用层来说, 是透明的, 无感知的。所以, 你用socket编程的时候, 根本感觉不到这点。
其实, 到这里, 一切应该很明白了。 最后说两个不太重要的事:
1. 网络包中有很多0000, 这个不是真正的业务数据, 跟我的tcpdump有关, 可以忽略。
2. tcp实验中, 在服务端和客户端抓包, 发现都进行了tcp分段, 这是很好理解的。 但是, 在udp实验中, 服务端抓包进行了分片, 但客户端抓包发现, 居然没有预期中的分片。 其实, 猜想一下, 这也不难理解, 应该是tcpdump抓包的时机/地点的原因, 这个应该是与tcpdump的实现有关。 待到来日, 如果查明此问题, 再来叙述。 不过, 这个问题暂时看来, 不太重要。 不影响我们对本博文内容的理解。( 后来: 通过更深入的学习, 发现可能与gso相关)
原文链接:https://blog.csdn.net/stpeace/article/details/74152332