我有一個專用局域網的網絡應用程序。我正在使用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);
}
我不會在這裏閱讀整個代碼,而是問一個概念問題:服務器定期發送到廣播,是嗎?或者只是一次'你好,我在這裏'? –
服務器通過廣播發送一系列數據報。數據是這樣的,任何客戶端實例都可以在數據流的「中間」選擇並開始執行它。 – meissnersd
廣播到255.255.255.255已被棄用約20年。您應該使用子網定向廣播。你也不需要在同一個進程中使用兩個UDP套接字:一個就可以。 – EJP