与服务器TcpClient的通讯保持C#的活动连接?
我有这样的TcpClient code,工作正常。它连接到perl服务器上的Linux系统,并收到任何服务器的货物内给它。很好地工作。
I've this TcpClient code which works fine. It connects to perl server on linux system and receives anything that server sents to it. Works nicely.
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));
}
}
然而,在某些情况下,我有一些问题是:
However in certain conditions I'm having some problems with it:
- 在我的作品上常常滴经过一段空闲时间,所以我的服务器已经实现,所以当它收到PING用PONG回应的连接。我可以用UDP发送PING服务器,它会与PONG回应的TCP但我会preFER内置的方式转换成TCP客户端,以便它发送PING每60秒左右。即使UDP的解决方案是可以接受我对
字符串varReadData = Encoding.ASCII.GetString没有超时(数据,0字节).Trim();
所以当PONG没有按'牛逼到我的客户甚至不反正注意到它。它只是一直等待......这使我.. - 在我的另一个问题是,在一些点
字符串varReadData = Encoding.ASCII.GetString(数据,0字节).Trim();
,这是等待数据的所有时间。当服务器崩溃或断开连接我的客户,我不察觉的。我想服务器拥有某种暂停
或检查连接处于活动状态。如果不是主动就应该尝试重新连接。
- My work connection often drops connection after some idle time so I've implemented in server so when it receives PING it responds with PONG. I can send PING with UDP to server and it will respond with PONG on tcp but i would prefer built-in way into tcp client so it does send PING every 60 seconds or so. Even if UDP solution would be acceptable I have no timeout on
string varReadData = Encoding.ASCII.GetString(data, 0, bytes).Trim();
so when PONG doesn't arrive my client doesn't even notice it anyway. It just keeps waiting ... which brings me to.. - My other problem is that at some point
string varReadData = Encoding.ASCII.GetString(data, 0, bytes).Trim();
this is waiting for data all the time. When server crashes or disconnects my client i don't even notice that. I would like server to have some kind oftimeout
or check if connection is active. If it's not active it should try to reconnect.
什么是解决这一问题的TcpClient最简单的方法?如何实现这两种方式的沟通,确保如果服务器断开连接我或我的网络断开连接的客户端会注意到这一点,并重新建立连接?
What would be simplest way to fix this TcpClient ? How do i implement both way communication making sure that if server drops my connections or my net gets disconnected client will notice it and reestablish connection ?
这不是 Encoding.ASCII.GetString(数据,0字节).Trim();
的永远的块,这是 stream.Read()
如果你读,你不能轻易的服务器(或任何NAT网关插图中)丢弃您的连接,并在服务器根本就没有什么可以送你的情况加以区分。 ATLEAST在将TCP FIN / RST包没有到达你的客户在发生故障或NAT网关的默默丢弃您的连接情况。
It's not Encoding.ASCII.GetString(data, 0, bytes).Trim();
that blocks forever, it's the stream.Read()
If you're reading, you can't easily distinguish between the server(or any NAT gateway inbetween) dropping your connection , and the case where the server simply doesn't have anything to send you. Atleast in the case where the TCP FIN/RST packets doesn't reach your client in case of failure, or a NAT gateway silently dropping your connection.
你可以做什么;
- 设置发送/ ReceiveTimeout ,然后ping服务器,如果发生超时,或在你的TCP连接,实现自己的心跳消息。重新建立或采取其他措施,如果你没有在合理时间内接收到心跳。
- 将 TCP保持选项,并且依赖于告诉你如果服务器已经一去不复返了。见code here.
- Set a Send/ReceiveTimeout , and ping the server if a timeout occurs, or implement your own heartbeat messages over your TCP connection. Reestablish or take other actions if you don't receive a heartbeat within a reasonable time.
- Set the TCP keepalive option, and rely on that to tell you if the server is gone. See code here.
最后一点会告诉你,如果TCP连接失败,它不会告诉你,如果服务器已经有点失败 - 如:如果按CTRL + Z你的perl服务器,它会只是坐在那里什么都不做的TCP窗口关闭,所以你可能需要实现自己的heatbeat messges覆盖这种情况太多,如果你需要。
The last point will tell you if the tcp connection fails, it won't tell you if the server has somewhat failed - e.g. if you CTRL+Z your perl server, it'll just sit there not doing anything as the tcp window closes , so you might need to implement your own heatbeat messges to cover such a case too if you need to.