2014-09-23 42 views
3

我想配置編程一個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; 
} 

回答

0

你做了錯誤的事情。您應該在接收器處發送套接字接收緩衝區大小。

+0

對不起,但我不確定我是否理解你的答案,請你擴展它? – sergico 2016-11-04 08:26:52

相關問題