2010-03-05 141 views
0

結合在C++中,當我運行(紅色警報!僞代碼)雙UDP套接字在兩個不同的UDP套接字在Linux中

bind(s1, <local address:port1234>) 
bind(s2, <local address:port1234>) 

s1s2一起socket()電話每次創建)我得到的問題。在Linux(Ubuntu)中,雙重綁定似乎很好。但是,在Windows中,雙重綁定失敗,並且第二次調用bind()的地址返回!= 0

我想在我的Linux機器上獲得Windows上的行爲。我可以使用一些設置來獲得Linux上的「端口繁忙」嗎?

+1

你能發表真實的代碼嗎?在你問我之前,我非常確定你*會*在第二次綁定時發生錯誤。 – 2010-03-05 04:41:58

+3

我也這麼認爲,所以我測試了它。在socket()調用之後,第二個bind()到同一個端口將返回EADDRINUSE。 – msw 2010-03-05 04:47:35

回答

4

請參閱bindsetsockopt。除非你用SO_REUSEADDR調用了setsockopt,否則你使用相同的地址調用bind應該會導致EADDRINUSE失敗。

+0

你是對的錢! SO_REUSEADDR在Windows和Linux(BSD-sockets?)中的工作方式不同。 – 2010-03-05 04:51:48

+0

雖然SO_REUSEADDR不允許您綁定到端點兩次。其目的是在關閉TCP套接字後覆蓋TIME_WAIT狀態。通常,操作系統會在TIME_WAIT中保留一個TCP套接字幾分鐘來拾取尚未到達的任何「遲到」數據包。如果你嘗試打開一個新的套接字,你會得到EADDRINUSE,除非你指定了殺死TIME_WAIT套接字的SO_REUSEADDR。 – 2010-03-05 05:25:43

+0

@ JohnKugelman-實際上並非如此;在Linux和UDP上,SO_REUSEADDR實際上允許您同時綁定到同一端點的多個套接字。這不同於Linux + TCP的語義,也不同於BSD上的語義。 – 2014-01-15 18:04:05

0

你確定嗎?據man 7 ip在我的Linux機器(Fedora 9中):

當一個進程想要接收新傳入的數據包或連接,它應該套接字使用綁定綁定到一個本地接口地址(2)。 只有一個IP套接字可以綁定到任何給定的本地(地址,端口)對。

沒有爲UDP例外在任一man 7 ipman 7 udp結合的沒有提及。 (這不能證明任何事情,但在這種情況下非文件化的行爲是......令人驚訝的)。

2

這不是我在Linux上得到的行爲。當我運行下面的測試程序,第二bind調用失敗EADDRINUSE

#include <stdio.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 

int main() 
{ 
    int s1, s2; 
    struct sockaddr_in sa = { 
     .sin_family = AF_INET, 
     .sin_port = 0x5555, 
     .sin_addr.s_addr = INADDR_ANY }; 

    s1 = socket(PF_INET, SOCK_DGRAM, 0); 
    s2 = socket(PF_INET, SOCK_DGRAM, 0); 
    if (bind(s1, (struct sockaddr *)&sa, sizeof sa) < 0) 
     perror("bind 1"); 
    if (bind(s2, (struct sockaddr *)&sa, sizeof sa) < 0) 
     perror("bind 2"); 

    return 0; 
} 
+0

對於代碼示例(我即將發佈一個,但現在不會:-P)的+​​1,但地址族(即,在「sin_family」字段中)應使用小的nit:AF_INET。 – 2010-03-05 04:51:16

+0

我個人在'socket'調用中也使用了'AF_INET' --- Open Group Base Specification實際上沒有任何'PF_ *'常量---但我可以看到更多的「寬鬆」套接字和其他非地址用法。 – 2010-03-05 04:52:15

+0

正確的你是先生,更新(Linux手冊頁說,使用'PF_'常量爲'socket()'的參數,但我相信沒有實際區別)。 – caf 2010-03-05 04:56:41