我正在编写一个简单的 C# tcp 消息服务器,它需要响应这样一个事实,即连接的客户端在最后一个 TimeSpan timeout 中保持沉默。换句话说

  • 客户端 A 连接。
  • 客户端 A 发送东西。
  • 服务器响应客户端 A。
  • 客户端 B 连接。
  • timeout 时间过去了,客户端 A 没有发送任何东西。
  • 服务器向 A.
  • 发送“ping”(不是网络 ping,而是消息 SendPing )
  • 客户端 B 发送东西。
  • 服务器响应。
  • pingTimeout 向 A 发送 ping 后的时间,断开与 A 的连接,并删除客户端。
  • 如果 B 沉默太久,也会发生同样的情况。

  • 简单的故事。如果在 client[n] 中没有从 timeout 听到任何字,则发送 ping。如果响应 ping,只需更新 client[n].LastReceivedTime ,但是,如果 client[n] 未能在 pingTimeout 内响应,则断开连接。

    据我所知,这必须通过某种调度程序来完成,导致简单地制作一个循环,说这样的话
    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();
        }
    }
    

    只会炸掉 CPU,一点好处也没有。是否有一个很好的简单算法/类来处理这样的情况,可以很容易地在 C# 中实现?并且它需要同时支持 100-500 个客户端(至少,如果它可以处理更多,则它是积极的)。

    最佳答案

    您的解决方案是好的,我认为如果您使用专用线程并在其中放置一个 Thread.Sleep(1000),那么您就不会像您所说的那样炸 CPU。避免在这个线程上阻塞调用,例如确保你对 SendPingDrop 的调用是异步的,这样这个线程只做一件事。

    另一种解决方案是为每个客户端连接使用一个 System.Timers.Timer,其间隔等于您的 ping 计时器。我正在使用这种方法,并且已经在 500 个客户端上进行了测试,没有出现任何问题。 (20 秒间隔)。如果您的间隔要短得多,我不建议这样做,并使用单线程查看其他解决方案(如您的解决方案)

    关于c# - 在 C# 中处理 TCP 服务器中的用户超时,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8343221/

    10-15 16:42