Reputation: 9259
I want to use UDP-Sockets for my XNA-Networkgame. And now I am trying to code a reliable Listenerthread, but there are some Problems.
If I use socket.Receive it will wait until a packet. This is fine for my Listenerthread. My thread has a while-loop like this:
while(Listen == true)
{
socket.Receive(...);
}
But if I swap the Listen-Flag to false (if I want to stop listening), it will stuck in the last .Receive().
Then I looked at the Methodes .BeginReceive(). It will call a methode if a packet arrived. But to receive the data I have to use .EndReceive() and that is the point I have a problem with. I want to still listen for packets and don't stop listening if a packet is arriving.
So I still use the blocking version with ".Receive()". I could force the listening thread to cancel by calling: Thread.abort(), but this is not good.
Currently I test if data is available:
while(Listen == true)
{
if(socket.Available > 0)
{
socket.Receive(...);
}
}
But I think this isn't the best way... If shortly after the if-clause a other thread is calling socket.Receive(..) it will stuck unintentional again. Is there no way to cancel the .Receive(..) method? I tried to set a timeout, but if .Receive timesout, it will throw an exception...
I want a simple udp-listening-thread, I can stop gracefully. :-) In MSDN I didn't find a listener-example which is listening for more than one packet. How handle other programmer this?
Upvotes: 8
Views: 15610
Reputation: 9259
Thank you Lirik and Matt Davis. It works fine, but is it ok to use Exceptions for this? I've learned that exceptions only should be thrown if something bad/unexpected happens. (to stop the blocking methode is intended :-) )
I handled the exception like this. I look for the errorcode and then break the loop.
try
{
broadcastSocket.ReceiveFrom(returnData, ref ep);
//...
}
catch (SocketException ex)
{
if (ex.ErrorCode == 10004)
{
break;
}
}
Why i have to use
socket.Shutdown(SocketShutdown.Both);
before
socket.Close();
Will .Close() not shutdown the socket as well?
And if i want to use the socket again, is there a "Restart"-methode oder must i create a new socketinstance?
Greetings user437899
Upvotes: 1
Reputation: 40345
Mark the Listen
flag as volatile, so changes can be visible between threads.
public volatile bool Listen{get; set;}
Handle the appropriate exceptions in your thread:
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();
In the code where you're switching the Listen
flag to false
you either close the socket or you interrupt the thread:
Listen = false;
socket.Shutdown(SocketShutdown.Both);
socket.Close();
//
// OR
//
listener.Interrupt();
Upvotes: 9