TcpClient server connection to maintain connection in c #?

I have a TcpClient code that works fine. It connects to the perl server on a Linux system and receives everything that the server passes to it. It works beautifully.

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, under certain conditions, I have some problems:

  • My working connection often disconnects the connection after some downtime, so I implemented it on the server, so when it receives PING, it answers PONG. I can send PING from UDP to the server and it will reply PONG to tcp, but I would prefer the built-in method to the tcp client so that it sends PING every 60 seconds or so. Even if the UDP solution is acceptable, I don’t have a timeout on the string varReadData = Encoding.ASCII.GetString(data, 0, bytes).Trim(); , therefore, when PONG does not come, my client does not even notice it. He just keeps waiting ... that brings me to ...
  • My other problem is that at some point string varReadData = Encoding.ASCII.GetString(data, 0, bytes).Trim(); it is waiting for data all the time. When the server crashes or shuts down my client, I don’t even notice it. I would like the server to have some kind of timeout or check if the connection is enabled. If it is inactive, it should try to reconnect.

What would be the easiest way to fix this TcpClient? How to implement two-way communication, making sure that if the server refuses my connections or my network disconnects, the client will notice this and reconnect?

+3
source share
2 answers

It is not Encoding.ASCII.GetString(data, 0, bytes).Trim(); which blocks forever, it is stream.Read() If you read, you cannot easily distinguish the server (or any NAT gateway between them), discarding your connection, and the case when the server simply can not send you anything. At least in the case when TCP FIN / RST packets do not reach your client in the event of a failure, or the NAT gateway silently disconnects your connection.

What can you do,

  • Set Send / ReceiveTimeout and ping the server if a timeout occurs, or execute your own heartbeat messages on your TCP connection. Restore or take other actions if you do not receive the heartbeat in a reasonable amount of time.
  • Set the TCP keepalive parameter and rely on this to tell you if there is a server. See the code here .

The last point will tell you if the tcp connection fails, it will not tell you that the server has worked somewhat - for example. if you CTRL + Z is your perl server, it just sits there, doing nothing, since the tcp window closes, so you may need to implement your own heat bits to cover this if you need to.

+4
source

You must get rid of the beating attempt in UDP and set up a real TCP beating on the network . Pinging a server using UDP is almost pointless.

Your protocol also lacks message framing .

Read both of these related articles (especially posting). The protocol you are currently using needs to be seriously revised.

+2
source

Source: https://habr.com/ru/post/1502567/


All Articles