Alxandr
Alxandr

Reputation: 12423

Handling user-timeouts in TCP server in C#

I'm writing a simple C# tcp message-server that needs to respond to the fact that a connected client has been silent the last TimeSpan timeout. In other words

  1. Client A connects.
  2. Client A sends stuff.
  3. Server responds to client A.
  4. Client B connects.
  5. timeout time passes without client A sending anything.
  6. Server sends "ping" (not as in network-ping, but as in a message, SendPing) to A.
  7. Client B sends stuff.
  8. Server responds.
  9. pingTimeout time after ping was sent to A, connection to A is dropped, and the client is removed.
  10. Same happens if B is silent too long.

Simple story short. If no word has been heard from client[n] within timeout, send ping. If ping is replied to, simply update client[n].LastReceivedTime, however, if client[n] fails to respond within pingTimeout, drop the connection.

As far as I understand, this must be done with some kind of scheduler, cause simply making a loop which says something like this

while(true) {
    foreach(var c in clients) {
        if(DateTime.Now.Subtract(c.LastReceivedTime) >= timeout && !c.WaitingPing)
            c.SendPing();
        else if(DateTime.Now.Subtract(c.LastReceivedTime) >= timeout + pingTimeout && c.WaitingPing)
            c.Drop();
    }
}

would simply fry the CPU and would be no good at all. Is there a good simple algorithm/class for handling cases like this that can easily be implemented in C#? And it needs to support 100-500 clients at once (as a minimum, it is only positive if it can handle more).

Upvotes: 3

Views: 294

Answers (1)

wal
wal

Reputation: 17719

Your solution would be Ok I think if you use a dedicated thread and put a Thread.Sleep(1000) in there so you dont as you say fry the CPU. Avoid blocking calls on this thread eg make sure your calls to SendPing and Drop are asynchronous so this thread only does one thing.

The other solution is to use a System.Timers.Timer per client connection which has an interval equal to your ping timer. I'm using this method and have tested this with 500 clients with no issues. (20 sec interval). If your interval is much shorter I would not recommend this and look at other solutions using a single thread to check (like your solution)

Upvotes: 2

Related Questions