UNIX网络编程6 从tcpdump了解到的TCP/UDP发送限制和缓冲区问题

本节主要解决的问题:MTU和TCP/UDP一次发送的大小限制,read/write 或者 send/recv返回时机和数值,内核发送和接收缓冲区大小,未解决通告窗口win大小和发送包长length的关系,内核TCP再往下层的实现未关注。

一些结论:
首先明白,用户空间缓冲区就是指你的程序中存放原始数据的和用于接收数据的char数组,内核空间的tcp收发缓冲区有默认值,也会自动动态地增加,也可以手动setsockopt()设置,应用程序中要发送的数据首先是从用户空间中拷贝到内核中的缓冲区里面。
关于MTU和TCP/UDP一次发送字节的大小:
1)最大传输单元MTU,不同的链路有不同的值,比如lo本地回环接口的MTU是65536,以太网的MTU是1500(这表示了IP层及以上,一个包的长度最大为1500,除了IP头和TCP头,可用的数据长度为1460字节)。
2)对于UDP比较简单,不管是本地回环测试,还是远程测试,发送端一次能发送的数据大小为65507(超过这个值,sendto直接返回-1,并且errno对应的出错信息为Message too long),tcpdump抓到的UDP包也是65507,接收端应用程序中的用户空间缓冲区(传递给recvfrom的字符数组大小)足够大的话,也是一次性返回这么多的数据,如果用户空间缓冲区不够大的话只能收到缓冲区这么多的数据。 所以说,对于UDP的使用,一次发送的数据要限制在65507以内,并且保证接收端的用户空间缓冲区足够大,UDP的发送限制可能是受限于65535(65535-20IP头-8UDP头),并不受限于MTU
3)对于TCP而言,情况比较复杂。经过以太网链路的,受到MTU=1500的限制,tcpdump抓到的包最大是1460(通常都是连续的1460包,只有最后一个比1460小),发送端发送如1024*1024的字节,send()或者write()调用都是一次返回;接收端recv()和read()可能一次返回也可能多次返回(视数据量大小和用户空间缓冲区大小而定),一般是将多个连续分组组装成一段后返回给用户空间。当本地回环测试时,MTU=65536,每个包的大小通常是32741甚至还有53056这么大。 所以说,对于TCP的使用,考虑MTU=1500,如果用户数据不超过1460,TCP发向底层时是不需要分片的;当超过MTU-40,TCP层就不得不拆分数据,发送多个分组。而用户在调用send()或write()时,这里基本上不会有大小限制(具体有待考证,查看内核源码,至少不能超过INT_MAX),你可以一下子发送几MB的数据,send()和write()调用也可以正确返回
关于read/write和send/recv返回时机和数据的问题:
上面已经做了一些分析,对于write和send发送数据,用户空间的数据被发送到系统中底层的TCP发送缓冲区后,函数就返回发送的字节数, 暂时没测到发送阻塞;read和recv是在socket为BLOCK时,如果没有数据则阻塞,发送端发送N个字节,接收端调用read/recv不一定会一次性收到N个字节,这是由于存在缓冲区、数据分片重组的存在,但一定是按序的, 非阻塞、数据接收完、数据填满了一次用户空间缓冲区,read/recv都会返回,即便是用户空间缓冲区足够大,也有可能只收到一部分就返回,具体需要根据read/recv的返回值确定,使用while来保证读取完毕。另外,write()函数对应的系统调用是write(),而send()和sendto()对应的系统调用都是sendto(),具体可以通过strace跟踪得到,或者直接去看socket源码。
关于内核中TCP发送和接收缓冲区的大小:
可以查看 /proc/sys/net/ipv4/tcp_rmem和tcp_wmem,接收和发送缓冲区都有默认值,典型的读、写缓冲区大小分别为87380、16384。这两个缓冲区的大小可以手动改变,通过setsockopt设置,而且也会自动扩大,当发送较大数据时,发送端的写缓冲区SO_SNDBUF会增大但并不一定非要比用户空间要发送的字节数大。

具体实验:
tcpdump使用介绍:http://blog.csdn.net/kobejayandy/article/details/17208137
只需要了解:-i 网络接口,-nn以IP和端口的方式显示主机,-A以ascii的方式显示数据包可以查看包中的内容,最后的参数在单引号中增加一些端口和IP的限制,比如'port 8888'就只抓取8888端口的数据包。

一、TCP
本地回环测试TCP,发送端发送数据1024*1024字节,接收端用户空间缓冲区1024*1024:
[ec2-user@ip-172-31-11-211 cplus]$ sudo tcpdump -i lo
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes

三次握手:
07:32:47.786242 IP ip-172-31-11-211.ap-northeast-1.compute.internal.35318 > ip-172-31-11-211.ap-northeast-1.compute.internal.ddi-tcp-1: Flags [S],  seq 517704113, win 65495, options [mss 65495,sackOK,TS val 4246348730 ecr 0,nop,wscale 6], length 0
07:32:47.786253 IP ip-172-31-11-211.ap-northeast-1.compute.internal.ddi-tcp-1 > ip-172-31-11-211.ap-northeast-1.compute.internal.35318: Flags [S.],  seq 3437879959ack 517704114win 65483, options [mss 65495,sackOK,TS val 4246348730 ecr 4246348730,nop,wscale 6], length 0
07:32:47.786262 IP ip-172-31-11-211.ap-northeast-1.compute.internal.35318 > ip-172-31-11-211.ap-northeast-1.compute.internal.ddi-tcp-1: Flags [.],  ack 1, win 1024, options [nop,nop,TS val 4246348730 ecr 4246348730], length 0

07:32:47.787397 IP ip-172-31-11-211.ap-northeast-1.compute.internal.35318 > ip-172-31-11-211.ap-northeast-1.compute.internal.ddi-tcp-1: Flags [.],  seq 1:32742, ack 1, win 1024, options [nop,nop,TS val 4246348731 ecr 4246348730],  length 32741
07:32:47.787403 IP ip-172-31-11-211.ap-northeast-1.compute.internal.ddi-tcp-1 > ip-172-31-11-211.ap-northeast-1.compute.internal.35318: Flags [.],  ack 32742, win 1658, options [nop,nop,TS val 4246348732 ecr 4246348731], length 0
07:32:47.787598 IP ip-172-31-11-211.ap-northeast-1.compute.internal.35318 > ip-172-31-11-211.ap-northeast-1.compute.internal.ddi-tcp-1: Flags [P.],  seq 32742:65483, ack 1, win 1024, options [nop,nop,TS val 4246348732 ecr 4246348730],  length 32741
07:32:47.787816 IP ip-172-31-11-211.ap-northeast-1.compute.internal.35318 > ip-172-31-11-211.ap-northeast-1.compute.internal.ddi-tcp-1: Flags [.],  seq 65483:98224, ack 1, win 1024, options [nop,nop,TS val 4246348732 ecr 4246348732],  length 32741
07:32:47.787823 IP ip-172-31-11-211.ap-northeast-1.compute.internal.35318 > ip-172-31-11-211.ap-northeast-1.compute.internal.ddi-tcp-1: Flags [P.],  seq 98224:130965, ack 1, win 1024, options [nop,nop,TS val 4246348732 ecr 4246348732],  length 32741
07:32:47.788262 IP ip-172-31-11-211.ap-northeast-1.compute.internal.ddi-tcp-1 > ip-172-31-11-211.ap-northeast-1.compute.internal.35318: Flags [.],  ack 130965, win 2047, options [nop,nop,TS val 4246348732 ecr 4246348732], length 0
收到了1:130964,向上返回给用户空间,一次recv或者read返回,长度130964 

07:32:47.788329 IP ip-172-31-11-211.ap-northeast-1.compute.internal.35318 > ip-172-31-11-211.ap-northeast-1.compute.internal.ddi-tcp-1: Flags [.],  seq 130965:163706, ack 1, win 1024, options [nop,nop,TS val 4246348732 ecr 4246348732],  length 32741
07:32:47.788337 IP ip-172-31-11-211.ap-northeast-1.compute.internal.35318 > ip-172-31-11-211.ap-northeast-1.compute.internal.ddi-tcp-1: Flags [P.],  seq 163706:196447, ack 1, win 1024, options [nop,nop,TS val 4246348732 ecr 4246348732],  length 32741
07:32:47.788345 IP ip-172-31-11-211.ap-northeast-1.compute.internal.35318 > ip-172-31-11-211.ap-northeast-1.compute.internal.ddi-tcp-1: Flags [.],  seq 196447:229188, ack 1, win 1024, options [nop,nop,TS val 4246348732 ecr 4246348732],  length 32741
07:32:47.788351 IP ip-172-31-11-211.ap-northeast-1.compute.internal.35318 > ip-172-31-11-211.ap-northeast-1.compute.internal.ddi-tcp-1: Flags [P.],  seq 229188:261929, ack 1, win 1024, options [nop,nop,TS val 4246348732 ecr 4246348732],  length 32741<
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值