为什么getsockopt()不会返回TCP_MAXSEG的期望值?

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

根据男子7 tcp

TCP_MAXSEG传出TCP数据包的最大段大小。 如果在连接build立之前设置了这个选项,它也会改变在初始数据包中通告给另一端的MSS值。大于(最终的)接口MTU的值不起作用。 技术合作计划还将对所提供的价值施加最小和最大限度的限制。

这让我想我可以连接TCP套接字之前configuration该值。 我写了一小段代码来创build套接字,我使用setsockopt()来configurationMSS。 在我的testing中,我将这个mss设置为1000B。

代码调用setsockopt()后跟getsockopt()来仔细检查已正确configuration的值。 两个系统调用都返回0(没有错误)。 之后,我连接到远程主机通过tcpdumpvalidation使用的MSS是正确的。 在这里我看到:

  • getsockopt()返回的MSS值始终为536字节
  • tcpdump显示syn包中configuration的MSS

修改我的代码以连接套接字configurationMSS。

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

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

几个注意事项:

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

Solutions Collecting From Web of "为什么getsockopt()不会返回TCP_MAXSEG的期望值?"