我想配置编程一个GNU/Linux系统上我的TCP连接,特别是的Ubuntu 12.04,内核3.2.0-68泛型为什么getsockopt()不会返回TCP_MAXSEG的期望值?
根据人7 TCP的MSS
TCP_MAXSEG传出TCP数据包的最大段大小。如果这个 选项在连接建立之前被设置,它也会改变在初始数据包中向另一端宣布的 MSS值。大于(最终)接口MTU的值 不起作用。 TCP将 也强加其提供的价值的最小和最大范围。
这让我想我可以配置之前的值我连接了TCP套接字。 我写了一小段代码来创建套接字,并使用setsockopt()来配置MSS。 在我的测试中,我将mss设置为1000B。
代码调用setsockopt()后跟getsockopt()来仔细检查已正确配置的值。两个系统调用都返回0(没有错误)。之后,我连接到远程主机,通过tcpdump验证使用的mss是否正确。在这里我看到了什么:
- 从的getsockopt()返回MSS值始终是536字节
- tcpdump的显示配置的MSS SYN数据包
修改我的代码后配置的MSS 我连接插座。
- 从返回用getsockopt MSS值()是1448再见
有没有来解释这种行为的正确道路?
有两点要注意:
- 根据维基536 B = MaxIPDatagramSize - IPHeaderSize - TcpHeaderSize 这是为了避免IP分组分片。
- 创建套接字并连接它(没有setsockopt()调用),显示由getsockopt()返回的536 B的mss,但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;
}
对不起,但我不确定我是否理解你的答案,请你扩展它? – sergico 2016-11-04 08:26:52