为什么getsockopt()不返回TCP_MAXSEG的期望值? [英] Why getsockopt() does not return the expected value for TCP_MAXSEG?

查看:232
本文介绍了为什么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_MAXSEG传出TCP数据包的最大段大小.如果这 在建立连接之前设置了选项,它也会更改 MSS值在初始数据包的另一端宣布. 大于(最终)接口的MTU无效. TCP将 还将其最小和最大界限强加到提供的值上.

TCP_MAXSEG The maximum segment size for outgoing TCP packets. If this option is set before connection establishment, it also changes the MSS value announced to the other end in the initial packet.Values greater than the (eventual) interface MTU have no effect. TCP will also impose its minimum and maximum bounds over the value provided.

这让我想我可以在连接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 - TcpHeaderSize this 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的期望值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆