linux网络编程 getsockopt使用TCP_MAXSEG获取MSS时,MSS值与实际值不符问题。
程序员文章站
2022-07-01 20:32:40
...
学习UNP的时候,习题中有一个获取MSS值和RCVBUF值的练习
第一步:
创建套接字sockfd,在connect之前调用getsockopt函数获取系统中的MSS值和RCVBUF的值
第二步:
调用connect连接服务器端
第三步:
再次获取MSS值和RCVBUF的值
代码如下:
#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[n] = 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);
}
运行结果:
[[email protected] 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获取对端通告的值
[[email protected] 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字节)
问题:
为什么会产生这种结果?