views:

58

answers:

3

I am writing a game server that has a time limit. I will be accepting input accross a socket until the timer is done. I am using a forever loop to receive data from the client.

while(true)
{
    socket.Receive(buffer);
} 

I need to break out of this loop when the time limit ends.

Sorry I don't think I am being specific enough.

I have two players sending and receiving data asynchronously. The timer is used to keep track of the time for both players. I need to end the reception of data from both players and give back statistics about their game at the end of the timer.

A: 

Have a watchdog timer close the socket when timeout expires. It will cause a SocketException on your socket.Receive call so be prepared to catch it. I use the same mechanism for different purposes.

Solution 2: http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.receivetimeout.aspx but I don't know if it can be applied to your case.

Or, else, you might query the Available property of the socket that indicates how many bytes are ready to be read. But this involves a polling/spinlock, which is bad for performance. Even if you wanted to use a semaphore, which gives you the opportunity to set a maximum timeout, you still need "somebody" to release it when data is available

djechelon
A: 

I was Thinking that instead of creating an infinite loop. I could possibly use a non-blocking socket.

while(stillTime)
{
    if(socket.Available > 0)
    socket.Recieve(buffer);
}

And when timer goes off set stillTime to false.

Is this a better solution?

Ge3ng
+2  A: 

The best way to handle this is for the thead with the timer to call a stop method in the class where the socket receive method is. This class will have a AutoResetEvent member instance and in the while for the socket read check the event to see if you need to stop:

public class SomeClass {
    AutoResetEvent _stopEvent = new AutoResetEvent(false);
    Socket _socket;
    public void StopReceive() {
        _stopEvent.Set();
    }
    private void SomeMethod() {
        _socket.ReceiveTimeout = 5000;  // In milliseconds
        while(!_stopEvent.WaitOne(0)){
                _socket.Receive(buffer);
        }
    }
}

Edit: If you have two sockets for the two players on two different threads, with the third thread handling the timeout then the code in all three threads need access to the same event, and change the event to a ManualResetEvent. What I am not sure about is if you have one class that handles the timer thread, and another class that handles the socket read threads for the two players, or if they are handled by one class. If they are separate classes then for the above code you could pass the event in the constructor:

public class SomeClass {
    ManualResetEvent _stopEvent;
    Socket _socket;
    public SomeClass(ManualResetEvent stopEvent) {
        _stopEvent = stopEvent;
    }
    private void SomeMethod() {
        _socket.ReceiveTimeout = 5000;  // In milliseconds
        while(!_stopEvent.WaitOne(0)){
                _socket.Receive(buffer);
        }
    }
}

The timer thread could now call the Set() method in the ManualResetEvent instance and both while loops would terminate.

Steve Ellinger
This won't work because I have 2 players and they are sending data simultaneously. I need one timer to handle the entire game.
Ge3ng
I am not sure I understand, if you mean that you have two sockets and therefore two while loops then both while loops would need to use the same event, and the timeout thread could call the set event. Without knowing a little bit more of the structure of your code I am not sure how to proceed.
Steve Ellinger
Yeah I have two sockets, one for each player and they are one their own thread. The Game has its own thread which handles sending info back to the clients. I need the game to end both of the while loops when the timer finishes.
Ge3ng
See the edit in my answer
Steve Ellinger
Thanks a lot this is great.
Ge3ng