2010-09-02 151 views
7

我想爲我的XNA-Networkgame使用UDP-Sockets。 現在我試圖編寫一個可靠的Listenerthread,但有一些問題。C#:UDP偵聽線程

如果我使用socket.Receive它將等待一個包。這對我的Listenerthread來說很好。 我的線程有一個while循環是這樣的:

while(Listen == true) 
{ 
    socket.Receive(...); 
} 

但是,如果我換了監聽標誌設置爲false(如果我想停止聽),它會停留在最後.Receive()。

然後我看着Methodes .BeginReceive()。如果數據包到達,它將調用一個方法。 但是爲了接收數據,我必須使用.EndReceive(),這是我遇到的問題。我還想監聽數據包,如果數據包到達,不要停止監聽。

所以我仍然使用帶有「.Receive()」的阻止版本。我可以通過調用Thread.abort()來強制取消偵聽線程,但這並不好。

目前我測試數據是否可用:

while(Listen == true) 
{ 
    if(socket.Available > 0) 
    { 
     socket.Receive(...); 
    } 
} 

但我認爲這不是最好的辦法...如果 - 子句的其他線程調用socket.Receive(後不久,如果.. )它將再次陷入無意中。 有沒有辦法取消.Receive(..)方法? 我試圖設置超時,但如果.Receive超時,它會拋出一個異常...

我想要一個簡單的udp-listening-thread,我可以優雅地停下來。 :-) 在MSDN中,我沒有找到一個正在偵聽多個數據包的偵聽器示例。 如何處理其他程序員呢?

+0

「如果其他線程調用socket.Receive(..)的if子句後不久,」 - 這似乎暗示有多個線程從同一插座讀書? – Ragoczy 2010-09-02 13:17:41

+0

不,我不這樣做。 但它是可能的,我想避免:-) – user437899 2010-09-02 13:28:25

+1

當你準備好停止收聽時,關閉插座。阻塞'Receive()'方法將以'SocketException'退出,您需要捕獲它。 – 2010-09-02 13:47:48

回答

9

Listen標記標記爲volatile,因此可以在線程之間看到更改。

public volatile bool Listen{get; set;} 

處理您的線程的適當的例外:

Thread listener = new Thread(()=> 
{ 
    while(Listen == true) 
    { 
     try 
     { 
      socket.Receive(); 
     } 
     catch(ThreadInterruptException) 
     { 
      break; // exit the while loop 
     } 
     catch(SocketException) 
     { 
      break; // exit the while loop 
     } 
    } 
}); 
listener.IsBackground = true; 
listener.Start(); 

在代碼中你切換Listen標誌false你要麼關閉套接字,或者您中斷線程:

Listen = false; 

socket.Shutdown(SocketShutdown.Both); 
socket.Close(); 
// 
// OR 
// 
listener.Interrupt(); 
1

謝謝Lirik和Matt Davis。 它工作正常,但可以使用例外嗎? 我瞭解到,只有在發生意外事件時纔會拋出異常。 (停止阻塞方法的意圖是:-))

我處理了這樣的異常。我尋找錯誤代碼,然後打破循環。

   try 
       { 
        broadcastSocket.ReceiveFrom(returnData, ref ep); 

        //... 
       } 
       catch (SocketException ex) 
       { 
        if (ex.ErrorCode == 10004) 
        { 
         break; 
        } 
       } 

爲什麼我必須使用

socket.Shutdown(SocketShutdown.Both); 

socket.Close(); 

將.Close()不關閉套接字呢?

如果我想再次使用套接字,是否有「重新啓動」-methode或者我必須創建一個新的socketinstance?

問候 user437899

+0

使用異常退出阻塞調用非常好,所以不要擔心異常!關機會停止發送和接收,但Close會強制關閉套接字。如果要重新使用套接字,請調用Disconnect而不是Close。 – Kiril 2010-09-03 13:42:12