2010-09-02 110 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