欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

 

问题:

为什么会产生这种结果?

相关标签: linux TCP/IP MSS