2013-02-20 87 views
0

我正在編寫一個簡單的客戶端 - 服務器應用程序,它暫時將用於我自己的個人使用。我正在使用Winsock進行網絡通信。過去10年我沒有建立任何網絡,所以我很生疏。我想盡可能使用盡可能少的外部代碼,所以我寫了一個自制的服務器發現機制,如下所示。UDP上的recv()失敗

客戶端廣播包含綁定到任意端口的客戶端UDP套接字的「名稱」的消息,我將其稱爲客戶端的發現套接字。服務器recv()廣播,然後sendto()客戶端發現套接字的偵聽套接字的'名稱'。客戶端然後使用此信息連接到服務器(在不同的套接字上)。這種機制應該允許服務器將其監聽套接字綁定到它可以在動態端口範圍(49152-65535)內的第一個端口,並且允許客戶端發現服務器在哪裏以及它正在監聽的端口。

服務器部分正常工作:服務器接收廣播消息併成功發送其響應。

在客戶端,防火牆日誌顯示服務器的響應到達機器,並且它被髮送到正確的端口(到客戶端的發現套接字)。 但是這條消息從來沒有讓它到客戶端應用程序。我試過在阻塞和非阻塞模式下做recv(),並且從來沒有任何可用的數據。 ioctlsocket()始終顯示沒有數據可用,即使我知道數據包已將其發送到機器。

服務器成功對廣播數據執行recv()。但是,客戶端無法執行發送套接字的服務器響應的recv()。

這個問題非常模糊:在這種情況下應該注意什麼問題?爲什麼recv()無法獲得實際到達機器的數據包?套接字是UDP,所以它們沒有連接的事實是不相關的。或者是?

非常感謝提前。

回答

0

客戶端廣播包含綁定到任意端口的客戶端UDP套接字的'名稱'的消息,我將其稱爲客戶端的發現套接字。

該消息不需要包含任何內容。只需從廣播一個空的消息'發現套接字'。 recvfrom()會告訴服務器它來自哪裏,它可以直接回復。

服務器recv()廣播,然後sendto()客戶端發現套接字其偵聽套接字的'名稱'。

不夠公平,儘管實際上服務器可能每隔5秒或其他地方廣播自己的TCP偵聽端口。

在客戶端,防火牆日誌顯示服務器的響應到達機器,並且發送到正確的端口(到客戶端的發現套接字)。但是這個消息永遠不會讓它進入客戶端應用程序

如果到了主機,它必須到達應用程序。你肯定已經把這些港口弄混了。如上所述簡化並重試。

+0

謝謝EJP,我不知道recvfrom()不需要知道遠程地址;我會用它。 – user1752563 2013-02-22 16:10:41

+0

@ user1752563我沒有說recvfrom()不需要知道遠程地址。我說你可以通過使用recvfrom()獲得遠程地址,所以你不必把它放在有效載荷中。其實我可能會想到recvmsg();無論如何其中一個需要參數給你的源地址 – EJP 2013-02-22 22:11:25

+0

不,你是對的:你可以在未連接的數據報套接字上使用recvfrom,如果你傳遞適當的參數,你會被告知遠程套接字地址。 – user1752563 2013-02-23 10:02:42

0

嗯,它是那些愚蠢的情況之一:Windows防火牆除了其他防火牆以外,還在靜默地丟棄數據包。停用它解決了這個問題。

但我仍然不明白它是如何工作的,因爲它允許服務器接收通過廣播發送的數據包。當我的智慧結束了,並設置服務器通過廣播迴應時,這些數據包被丟棄了。

兩天的沮喪。我希望有人從我的經歷中獲利。