linux网络编程 getsockopt使用TCP_MAXSEG获取MSS时,MSS值与实际值不符问题。
2019-03-15 00:05
323 查看
学习UNP的时候,习题中有一个获取MSS值和RCVBUF值的练习
第一步:
创建套接字sockfd,在connect之前调用getsockopt函数获取系统中的MSS值和RCVBUF的值
第二步:
调用connect连接服务器端
第三步:
再次获取MSS值和RCVBUF的值
代码如下:
[code]#include "unp.h" #include <netinet/tcp.h> int main(int argc, char **argv) { int sockfd, n; char recvline[MAXLINE + 1]; struct sockaddr_in servaddr; if (argc != 2) err_quit("usage: a.out <IPaddress>"); if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) err_sys("socket error"); /*-----------------------------------------------------------------*/ //int rcvbuf=0,mss=0,mss1=0; //socklen_t len=sizeof(rcvbuf); //getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &len); //printf("RCVBUF = %d\n",rcvbuf); /*-----------------------------------------------------------------*/ bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(13); /* daytime server */ if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) err_quit("inet_pton error for %s", argv[1]); /*-----------------------------------------------------------------/ connect之前获取MSS值 /-----------------------------------------------------------------*/ int rcvbuf,mss; socklen_t len=sizeof(rcvbuf); getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &len); printf("RCVBUF = %d\n",rcvbuf); len=sizeof(mss); getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &len); printf("MSS = %d \n",mss); /*-----------------------------------------------------------------*/ if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0) err_sys("connect error"); /*-----------------------------------------------------------------/ 再次获取MSS值 /-----------------------------------------------------------------*/ rcvbuf=0; len=sizeof(rcvbuf); getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &len); printf("RCVBUF 1 = %d\n",rcvbuf); //fflush(NULL); mss=0; len=sizeof(mss); getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &len); printf("MSS 1 = %d \n",mss); //fflush(NULL); /*-----------------------------------------------------------------*/ int count = 0; while ( (n = read(sockfd, recvline, MAXLINE)) > 0) { count++; recvline = 0; /* null terminate */ if (fputs(recvline, stdout) == EOF) err_sys("fputs error"); } printf("count = %d\n",count); if (n < 0) err_sys("read error"); exit(0); }
运行结果:
[code][root@localhost test]# 7.2 127.0.0.1 RCVBUF = 87380 MSS = 536 RCVBUF 1 = 174758 MSS 1 = 32768 Thu Mar 14 08:12:56 2019 count = 1
我们可以看到,调用connect之前系统默认的值MSS=536,RCVBUF=87380
连接之后MSS=32768,RCVBUF=174758
MSS和RCVBUF的值都产生了变化,原因是连接以后,客户端的MSS将采用对端给定的MSS大小,UNP原话是这样说的
“一旦连接建立,本选项的值就是对端通告的MSS选项值,TCP不能发送超过该值的分节。——P172”
所以按照道理,对端通告的值应该是32768
我们现在利用tcpdump获取对端通告的值
[code][root@localhost day13]# tcpdump -i lo host 127.0.0.1 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes 08:12:56.694657 IP localhost.40966 > localhost.daytime: Flags [S], seq 2114825606, win 65495, options [mss 65495,sackOK,TS val 97357627 ecr 0,nop,wscale 6], length 0 08:12:56.694699 IP localhost.daytime > localhost.40966: Flags [S.], seq 929223868, ack 2114825607, win 65483, options [mss 65495,sackOK,TS val 97357627 ecr 97357627,nop,wscale 6], length 0 08:12:56.694725 IP localhost.40966 > localhost.daytime: Flags [.], ack 1, win 1024, options [nop,nop,TS val 97357627 ecr 97357627], length 0 08:12:56.695408 IP localhost.daytime > localhost.40966: Flags [P.], seq 1:27, ack 1, win 1024, options [nop,nop,TS val 97357627 ecr 97357627], length 26 08:12:56.695429 IP localhost.daytime > localhost.40966: Flags [F.], seq 27, ack 1, win 1024, options [nop,nop,TS val 97357627 ecr 97357627], length 0 08:12:56.695541 IP localhost.40966 > localhost.daytime: Flags [.], ack 27, win 1024, options [nop,nop,TS val 97357627 ecr 97357627], length 0 08:12:56.695736 IP localhost.40966 > localhost.daytime: Flags [F.], seq 1, ack 28, win 1024, options [nop,nop,TS val 97357627 ecr 97357627], length 0 08:12:56.695763 IP localhost.daytime > localhost.40966: Flags [.], ack 2, win 1024, options [nop,nop,TS val 97357627 ecr 97357627], length 0
然而tcpdump抓取的seq里显示的对端通告的MSS=65495(TCP最大正常窗口大小65535,TCP首部40字节)
问题:
为什么会产生这种结果?
相关文章推荐
- Linux网络编程之 TCP 粘包问题
- Linux网络编程之TCP粘包问题3
- linux网络编程--TCP分包 粘包 MTU 和MSS之间的关系分析
- linux网络编程之IP协议首部格式与其配套使用的四个协议(ARP,RARP,ICMP,IGMP)和TCP、UDP协议头结构总结
- Linux网络编程--使用epoll模型同时处理tcp和udp服务
- Linux网络编程----bind自动获取自己的IP和PORT,端口使用的注意事项
- 唯快不破:linux网络编程--TCP分包 粘包 MTU 和MSS之间的关系分析
- Linux网络编程:TCP服务器(单进程多用户),使用select方法实现
- Linux网络编程之使用TCP传输文件
- linux网络编程:使用进程池实现TCP多客户服务
- Linux网络编程 使用epoll实现一个高性能TCP Echo服务器
- linux网络编程--TCP分包 粘包 MTU 和MSS之间的关系分析
- Linux 网络编程之TCP粘包问题2
- Linux网络编程之使用TCP传输文件
- Linux网络编程:基于TCP的程序开发回顾篇
- 编程获取Linux的cpu占用率和 mem使用情况
- 使用Tcp网络编程上传图片。
- 【Linux网络编程笔记】TCP短连接产生大量TIME_WAIT导致无法对外建立新TCP连接的原因及解决方法—基础知识篇
- [转]在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(二)
- 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(一)----基础类库部分