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

根据 man 7 tcp



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

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

  • 从 getsockopt() 返回的 MSS 值始终为 536 字节
  • tcpdump 显示同步包中配置的 MSS

  • 连接套接字后修改了我的代码以配置MSS。
  • 从getsockopt() 返回的MSS 值是1448 再见

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

    一些注意事项:
  • 根据维基百科 536 B = MaxIPDatagramSize - IPHeaderSize - TcpHeaderSize
    这是为了避免 IP 数据包碎片。
  • 创建一个套接字并连接它(没有 setsockopt() 调用),显示由 getsockopt() 返回的 mss 为 536 B,但 tcpdump 在 SYN 数据包中显示 1460 B 的 mss,这是有道理的 1500 - IpHeader - TcpHeader

  • 下面,如果你有兴趣,是我的代码:
    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;
    }
    

    最佳答案

    你做错了。您应该在接收器处发送套接字接收缓冲区大小。

    10-08 03:30