TcpClient与服务器通信以保持c#中的活动连接?

我有这个TcpClient代码,工作正常。 它连接到Linux系统上的perl服务器,并接收服务器发送给它的任何东西。 很好地工作。

public static void Main() { foreach (ProtocolConnection tcpConnection in TcpConnectionsList) { ProtocolConnection connection = tcpConnection; ThreadPool.QueueUserWorkItem(_ => { ThreadTcpClient(connection); ManualResetEventTcp.Set(); }); } ... Some code... } public static void TcpConnect(ProtocolConnection varConnection) { int retryCountSeconds = varConnection.RetryEverySeconds*Program.MilisecondsMultiplier; int count = 0; while (true) { try { using (var client = new TcpClient(varConnection.IpAddress.ToString(), varConnection.Port) { NoDelay = true }) using (var stream = client.GetStream()) { var data = new Byte[256]; while (!Program.PrepareExit) { Int32 bytes = stream.Read(data, 0, data.Length); string varReadData = Encoding.ASCII.GetString(data, 0, bytes).Trim(); if (varReadData != "" && varReadData != "PONG") { VerificationQueue.EnqueueData(varReadData); Logging.AddToLog("[TCP][" + varConnection.Name + "][DATA ARRIVED]" + varReadData); } else { Logging.AddToLog("[TCP]" + varReadData); } } } } catch (Exception e) { if (e.ToString().Contains("No connection could be made because the target machine actively refused it")) { Logging.AddToLog("[TCP][ERROR] Can't connect to server (" + varConnection.Name + ") " + varConnection.IpAddress + ":" + varConnection.Port ); } else { Logging.AddToLog(e.ToString()); } } DateTime startTimeFunction = DateTime.Now; do { Thread.Sleep(1000); } while (((DateTime.Now - startTimeFunction).TotalSeconds < retryCountSeconds)); } } 

但是在某些条件下我遇到了一些问题:

  1. 我的工作连接经常在一些空闲时间之后断开连接,所以我在服务器中实现,所以当它收到PING时它会以PONG响应。 我可以用服务器发送带有UDP的PING,它会在tcp上用PONG响应,但我更喜欢内置的方式进入tcp客户端,所以它每60秒左右发送一次PING。 即使UDP解决方案可以接受,我也没有超时string varReadData = Encoding.ASCII.GetString(data, 0, bytes).Trim(); 所以当PONG没有到达时,我的客户甚至都没有注意到它。 它只是在等待…这让我…
  2. 我的另一个问题是,在某些时候string varReadData = Encoding.ASCII.GetString(data, 0, bytes).Trim(); 这一直在等待数据。 当服务器崩溃或断开我的客户端时,我甚至都没有注意到。 我希望服务器有某种timeout或检查连接是否有效。 如果它不活动,它应该尝试重新连接。

修复此TcpClient最简单的方法是什么? 我如何实现双向通信,确保如果服务器丢失我的连接或我的网络断开客户端将注意到它并重新建立连接?

它不是Encoding.ASCII.GetString(data, 0, bytes).Trim(); 永远阻止,它是stream.Read()如果你正在阅读,你不能轻易区分服务器(或中间的任何NAT网关)丢弃你的连接,以及服务器根本没有任何东西的情况寄给你。 如果TCP FIN / RST数据包在发生故障时未到达您的客户端,或者NAT网关默默地丢弃您的连接,则至少应该这样做。

你可以做什么;

  • 设置发送/ 接收时间 ,并在发生超时时ping服务器,或通过TCP连接实现自己的心跳消息。 如果您在合理的时间内没有收到心跳,请重新建立或采取其他措施。
  • 设置TCP keepalive选项,并依赖它来告诉您服务器是否已经消失。 请参阅此处的代码

最后一点将告诉你tcp连接是否失败,它不会告诉你服务器是否有一些失败 – 例如,如果你CTRL + Z你的perl服务器,它只会坐在那里没有做任何事情,因为tcp窗口关闭,因此,如果需要,您可能需要实施自己的热量消息来覆盖这种情况。

您应该摆脱UDP心跳尝试并输入真正的TCP心跳 。 使用UDP“ping”服务器几乎毫无意义。

您的协议也缺少消息框架 。

仔细阅读这两个链接文章(特别是消息框架)。 您目前使用的协议确实需要严格修改。