我有这个 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));
}
}
但是在某些情况下我会遇到一些问题:
- 我的工作连接经常在一段空闲时间后断开连接,因此我在服务器中实现了这样,当它收到 PING 时,它会用 PONG 响应。我可以使用 UDP 向服务器发送 PING,它会在 tcp 上以 PONG 进行响应,但我更喜欢在 tcp 客户端中使用内置方式,因此它每隔 60 秒左右发送一次 PING。即使 UDP 解决方案可以接受,我也没有超时
string varReadData = Encoding.ASCII.GetString(data, 0, bytes).Trim();
所以当 PONG 没有到达时,我的客户甚至没有注意到它。它只是一直在等待......这让我......
- 我的另一个问题是在某个时候
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 网关默默地断开您的连接的情况下。
你可以做什么;
- 设置发送/接收超时 http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.receivetimeout.aspx,并在发生超时时 ping 服务器,或者通过 TCP 连接实现您自己的心跳消息。如果您在合理的时间内没有收到心跳,请重新建立或采取其他措施。
- Set the TCP保活 http://msdn.microsoft.com/en-us/library/1011kecd.aspx选项,并依靠它来告诉您服务器是否消失。查看代码here https://stackoverflow.com/questions/169170/what-is-the-best-way-to-do-keep-alive-socket-checking-in-net.
最后一点将告诉您 tcp 连接是否失败,但不会告诉您服务器是否出现某种故障 - 例如如果你 CTRL+Z 你的 perl 服务器,它只会坐在那里,当 tcp 窗口关闭时不做任何事情,所以如果你需要的话,你可能需要实现你自己的 heatbeat 消息来覆盖这种情况。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)