linux网络编程 getsockopt使用TCP_MAXSEG获取MSS时,MSS值与实际值不符问题。

 学习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);
}

 运行结果:

[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获取对端通告的值

[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字节)

 

问题:

为什么会产生这种结果?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值