2013-01-16 26 views
1

我有一個專用局域網的網絡應用程序。我正在使用loopback進行測試。當我在LAN上測試時,套接字創建順序並不重要。如果我使用循環返回127.0.0.1進行測試,那麼存在套接字創建順序問題。爲什麼它在迴路上有所不同?WinSock在環回中創建UDP套接字的順序。

這裏有更多的細節...

有一個服務器,和許多客戶端實例。服務器通過UDP廣泛傳播數據。客戶端接收並處理數據。

我需要網絡層不關心服務器或客戶端的啓動順序。爲我的案例管理流程很難。應用程序實例應該能夠以任意順序在網絡上啓動,並在發送時查看UDP端口上廣播的數據。

但是,我設置我的UDP套接字,這是強制排序發生的方式。我必須啓動客戶端,然後啓動服務器。如果我在服務器進行UDP廣播之後啓動客戶端,則客戶端套接字不會收到數據。如果我強制正在運行的服務器實例拆除並重建其UDP套接字,突然所有客戶端都開始接收數據。

如何創建套接字一定有問題。客戶端和服務器代碼使用共享函數庫來創建UDP套接字。所以服務器在m_fdOut上發送。客戶端的每個實例都在m_fdIn上接收。

我在這裏做錯了什麼?

SOCKET m_fdIn; 
SOCKET m_fdOut; 

if ((m_fdIn = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 
{ 
    WARNF("socket failed, winsock error %d\n", WSAGetLastError()); 
    exit(1); 
} 

if ((m_fdOut = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 
{ 
    WARNF("socket failed, winsock error %d\n", WSAGetLastError()); 
    exit(1); 
} 


int sockopt = 1; 
if (setsockopt(m_fdOut, SOL_SOCKET, SO_BROADCAST, (char *)&sockopt, 
    sizeof(sockopt)) < 0) 
{ 
    WARNF("setsockopt failed, winsock error %d\n", WSAGetLastError()); 
    exit(1); 
} 

sockopt = readPreference<int>("SOL_RCVBUF", 512*1024); 
if (setsockopt(m_fdIn, SOL_SOCKET, SO_RCVBUF, (char *)&sockopt, sizeof(sockopt)) < 0) 
{ 
    WARNF("setsockopt failed, winsock error %d\n", WSAGetLastError()); 
    exit(1); 
} 

sockopt = 1; 
if (setsockopt(m_fdIn, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(sockopt)) < 0) 
{ 
    WARNF("setsockopt failed, winsock error %d\n", WSAGetLastError()); 
    exit(1); 
} 

sockopt = readPreference<int>("IP_MULTICAST_TTL", 32); 
if (setsockopt(m_fdOut, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&sockopt, sizeof(sockopt)) < 0) 
{ 
    WARNF("setsockopt failed, winsock error %d\n", WSAGetLastError()); 
    exit(1); 
} 

String destAdd = "255.255.255.255" 
int portNumber = 1234; 
int n1, n2, n3 ,n4; 
if (sscanf(destAddr, "%d.%d.%d.%d", &n1, &n2, &n3, &n4) != 4) 
{ 
    n1 = n2 = n3 = n4 = 255; 
} 

u_long bcastAddr = (n1<<24) | (n2<<16) | (n3<<8) | n4; 
outAddr.sin_family = AF_INET; 
outAddr.sin_port = htons(portNumber); 
outAddr.sin_addr.s_addr = htonl(bcastAddr); 

struct sockaddr_in in_name; 
in_name.sin_family = AF_INET; 
in_name.sin_addr.s_addr = INADDR_ANY; 
in_name.sin_port = htons(portNumber); 

if (bind(m_fdIn, (struct sockaddr *)&in_name, sizeof(in_name)) < 0) 
{ 
    WARNF("bind failed, winsock error %d\n", WSAGetLastError()); 
    exit(1); 
} 
+0

我不會在這裏閱讀整個代碼,而是問一個概念問題:服務器定期發送到廣播,是嗎?或者只是一次'你好,我在這裏'? –

+0

服務器通過廣播發送一系列數據報。數據是這樣的,任何客戶端實例都可以在數據流的「中間」選擇並開始執行它。 – meissnersd

+0

廣播到255.255.255.255已被棄用約20年。您應該使用子網定向廣播。你也不需要在同一個進程中使用兩個UDP套接字:一個就可以。 – EJP

回答

0

所以我確實改變了從UDP廣播到多播的實現。這似乎工作在環回,所以多個進程可以共享端口。