【问题标题】:Why getsockopt() does not return the expected value for TCP_MAXSEG?为什么 getsockopt() 没有返回 TCP_MAXSEG 的预期值?
【发布时间】:2014-11-17 18:09:47
【问题描述】:

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

根据man 7 tcp

TCP_MAXSEG 传出 TCP 数据包的最大段大小。如果这 选项在连接建立之前设置,它也会改变 在初始数据包中向另一端宣布的 MSS 值。Values 大于(最终)接口 MTU 无效。 TCP 将 还将其最小和最大界限强加于所提供的值。

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

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

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

修改了我的代码以配置 MSS 我连接了套接字。

  • getsockopt() 返回的 MSS 值为 1448 Bye

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

几个注意事项:

  • 根据维基百科 536 B = MaxIPDatagramSize - IPHeaderSize - TcpHeaderSize 这是为了避免 IP 数据包碎片化。
  • 创建一个套接字并连接它(没有 setsockopt() 调用),显示由 getsockopt() 返回的 mss 为 536 B,但 tcpdump 在 SYN 数据包中显示宣布的 mss 为 1460 B,这是有意义的 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;
}

【问题讨论】:

    标签: c linux sockets tcp network-programming


    【解决方案1】:

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

    【讨论】:

    • 抱歉,我不确定我是否理解您的回答,能否请您扩展一下?
    猜你喜欢
    • 1970-01-01
    • 2010-10-19
    • 2015-03-21
    • 1970-01-01
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    • 2018-01-31
    相关资源
    最近更新 更多