【发布时间】:2014-05-23 07:49:16
【问题描述】:
我在 .NET(c# 或 vb.net)中创建了一个服务器-客户端通信程序,使用 TCPListener - 端口 8080 上的套接字。简而言之,该程序像聊天软件一样工作,客户端连接到服务器,两者兼而有之等待对方的消息,然后处理它。
为了从客户端检索数据包,我使用的是这样的“While”方法:
While true
Dim Buffer(4096) As Byte
s.Receive(Buffer)
Dim strDataReceived As String = System.Text.Encoding.ASCII.GetString(Buffer)
ProcessData(strDataReceived) 'Process data received...........
End while
在本地测试 server.exe-client.exe 时,软件可以正常运行几个小时,没有任何问题。
但是当我开始在我的真实服务器上运行 server.exe 时,服务器-客户端之间的连接通常会在客户端连接数十分钟后相互丢失。症状是客户端向服务器发送数据包,但当服务器仍处于“sck.receive(Buffer)”命令时,服务器没有收到来自客户端的数据包。我已经测试了很多次,但我仍然没有幸运地保持连接运行超过 1 小时。
我已经调查过这个问题,但仍然很奇怪:
服务器未安装任何防火墙软件。
客户端没有使用任何代理和杀毒、防火墙软件
我在服务器上使用带宽记录软件来确保我的服务器中的互联网是稳定的。
我从客户端计算机向服务器发出“ping -t”,并继续查看它以确保客户端和服务器之间没有丢失连接。 ping命令表示ping时间一般在5ms到50ms之间,不会出现连接超时。
我什至尝试在客户端计算机中拔下网线几秒钟,然后再次重新插入以模拟断开连接事件。我很高兴我的服务器-客户端之间的连接仍然保持不变,这不是导致我出现症状的问题。
如果收到超时,我正在考虑编写自动重新连接的代码。但是如果上述症状仍然存在,它可能会使我的软件在重新连接时通常会延迟。我真的很想知道我的代码有什么问题,解决上述症状的方法是什么?
【问题讨论】:
-
我不知道为什么它会中断一个真实的、实时的连接(可能是关于套接字空闲和关闭的一些事情),也许比我更了解 TCP 的人可以回答这个问题。但是,您真的想长时间保持连接空闲吗?在我见过的大多数实现中,想要让套接字长时间保持打开而不接收数据的软件会每隔一段时间发送一个保持活动数据包以确保套接字保持活动状态。哦,请确保您 a) 刷新流(如果它被缓冲)并且 b) 没有达到 nagle 效果
-
我发现通常是 ISP 断开了长时间运行的 TCP 连接。如果我是 OP,我会编写服务器以侦听传入连接而无需使用 while 循环。当客户端发送消息时,它会执行“连接 - 发送 - 断开连接”来发送消息。读取消息可以是不同的例程,其中客户端也设置为侦听而不是 while 循环。当客户端第一次连接时,即使断开连接,服务器也会将其保持为“这是一个打开的连接”,以便知道在有消息时向客户端发送消息。
-
我同意keealive数据包。但在谈论几十分钟时,他并没有达到 nagle 算法。那个算法不是那样工作的。缓冲/延迟在 TCP 堆栈内完成,并且在高传输率下也相关,而不是几分钟。堆栈将在几毫秒内自行刷新数据包。如果设置正确,您不必刷新 TCP 套接字。实际上,您无法在大多数操作系统上刷新它。也许通过切换 TCP_NODELAY,正如我在 Linux 上所读到的那样。如果有的话,nagle 只会损害性能。
-
我不确定 nagle 算法在这里是否相关 - 这更多地与组合短数据包以减少数据包头的开销有关。更有可能只是连接超时,因为没有任何流量。
-
是的,我为错误信息道歉。 Nagle 仅在您进行写入写入读取时在短时间内起作用。