本文介绍了为什么getsockopt()不返回TCP_MAXSEG的期望值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在GNU/Linux系统上,以编程方式配置我的TCP连接的 MSS ,特别是 Ubuntu 12.04,内核3.2.0-68-通用

I'm trying configuring programmatically the MSS of my TCP connection on a GNU/Linux system, specifically Ubuntu 12.04, kernel 3.2.0-68-generic

根据 man 7 tcp

这让我想我可以在连接TCP套接字之前配置之前的值.我写了一小段代码来创建套接字,并使用setsockopt()来配置MSS.在我的测试中,我将mss设置为1000B.

this let me think I can configure the value before I connect the TCP socket.I wrote a small chunk of code to create a socket and I used setsockopt() to configure the MSS.In my test I'm setting the mss to 1000B.

代码先调用setsockopt(),然后再调用getsockopt(),以仔细检查该值是否已正确配置.两个系统调用均返回0(无错误).之后,我连接到远程主机以通过tcpdump验证所使用的mss是否正确.这是我所看到的:

The code calls setsockopt() followed by getsockopt() to double check the value has been properly configured. Both syscalls return 0 (no error). After that I connect to a remote host to verify via tcpdump the used mss is correct. Here what I see:

  • 从getsockopt()返回的MSS值始终为536字节
  • tcpdump在syn数据包中显示已配置的MSS

修改我的代码以在连接套接字后 配置MSS.

Modified my code to configure the MSS after I connect the socket.

  • 从getsockopt()返回的MSS值是1448 Bye

有没有正确的方法来解释这种行为?

Is there a correct way to explain such behavior?

一些注意事项:

  • 根据维基百科536 B = MaxIPDatagramSize-IPHeaderSize-TcpHeaderSize这是为了避免IP数据包分段.
  • 创建一个套接字并连接它(不调用setsockopt()),显示getsockopt()返回的536 B的mss,但是tcpdump在SYN数据包中显示了一个宣布的1460 B的mss,这是有意义的1500-IpHeader- TcpHeader
  • according to wikipedia 536 B = MaxIPDatagramSize - IPHeaderSize - TcpHeaderSizethis is to avoid IP packet fragmentation.
  • creating a socket and connecting it (no setsockopt() call), displays an mss of 536 B returned by getsockopt() but tcpdump shows an announced mss of 1460 B in the SYN packet, that makes sense being 1500 - IpHeader - TcpHeader

下面是您的代码,如果您有兴趣的话

Below, if you are interested, is my code:

int setSocketMss( int i_sd, int i_mss )
{
    int res = 0;
    int mss = i_mss;
    socklen_t len = sizeof( mss );

    res = ::setsockopt( i_sd, IPPROTO_TCP, TCP_MAXSEG, &mss, len );
    if ( res < 0 )
    {
        qDebug() << "error: cannot configure mss for socket" << i_sd;
        return -1;
    }
    res = ::getsockopt( i_sd, IPPROTO_TCP, TCP_MAXSEG, &mss, &len );
    if ( mss != i_mss )
    {
        qDebug() << "MSS set to" << i_mss << "but read value is" << mss;
    }
    else
    {
        qDebug() << "MSS for socket" << i_sd << " has been set to" << mss;
    }
    return mss;
}

void configureAddrStruct( const QString & i_ipAddress,
                          quint16 i_port,
                          struct sockaddr_in & o_sockaddr )
{
    o_sockaddr.sin_addr.s_addr = htonl( QHostAddress(i_ipAddress).toIPv4Address() );
    o_sockaddr.sin_port = htons( i_port );
    o_sockaddr.sin_family = PF_INET;
    memset( o_sockaddr.sin_zero, 0, sizeof(o_sockaddr.sin_zero) );
}

int main(int argc, char *argv[])
{
    int sd = ::socket( PF_INET, SOCK_STREAM, getprotobyname("tcp")->p_proto );
    if ( -1 == sd )
    {
        qDebug() << "erro creating socket";
        exit (1);
    }
    else
    {
        qDebug() << "created socket:" << sd;
    }

    setSocketMss( sd, 1000 );

    struct sockaddr_in localAddress;
    struct sockaddr_in remoteAddress;

    configureAddrStruct( "192.168.23.7", 0, localAddress );
    configureAddrStruct( "192.168.23.176", 9999, remoteAddress );

    int res = ::bind( sd,
                      reinterpret_cast<const sockaddr *>( &localAddress ),
                      sizeof(localAddress) );
    if ( -1 == res )
    {
        qDebug() << "error binding socket to local address";
        exit(2);
    }

    //setSocketMss( sd, 1000 );

    res = ::connect( sd,
                     reinterpret_cast<const sockaddr*>( &remoteAddress ),
                     sizeof(remoteAddress) );
    if ( -1 == res )
    {
        qDebug() << "error connecting to remote host";
        ::perror( "connect()" );
        exit(2);
    }

    //setSocketMss( sd, 1000 );

    return 0;
}

推荐答案

您做错了事.您应该在接收方向套接字发送接收缓冲区大小.

You're doing the wrong thing. You should send the socket receive buffer size, at the receiver.

这篇关于为什么getsockopt()不返回TCP_MAXSEG的期望值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-22 18:34