的TcpListener / TcpClient的停止在某些情况下处理数据情况下、数据、在某些、TcpListener

2023-09-04 04:00:20 作者:默然沒有相愛

我有一个问题,即,这取决于两个网络设备的启动顺序上,我似乎失去接收一端数据的能力。

的设置是用C#(.NET 4.0)一个小小的服务器用于侦听数据从工业扫描器的特定端口,TCP通信。扫描仪连接到服务器应用程序就好了,并且将发送数据的小块(序列号)的服务器接收并处理。但是,重新启动(实际上,重新上电,不正常关闭其连接)扫描仪上导致服务器停止处理数据。事件引起的问题的顺序,以及该关键网络流量变为如下:

 成功失败
     | ---------------------- | | ---------------------- |
     |扫描仪|服务器| |扫描仪|服务器|
     | ---------------------- | | ---------------------- |
     | |开始| |开始| |
     |开始| | | |开始|
     |扫描|收到| |扫描|收到|
     |重新启动| | |重新启动| |
     --------(网络)------- --------(网络)-------
     | SYN | | | SYN | |
     | | ACK-123 | | | SYN ACK |
     | RST  -  123 | | | ACK | |
     | SYN | | | | |
     | | SYN ACK | | | |
     | ACK | | | | |
     | ---------------------- | | ---------------------- |
     |扫描|收到| |扫描| !输了! |
     | ---------------------- | | ---------------------- |
 

正如你所看到的,在成功的情况下,扫描仪重新启动后,服务器响应SYN一个ACK,和扫描仪重置连接,因为它意识到这是不正确的流。服务器检测到这一点,并优雅地处理它。然而,在失败情况下,服务器幸福地响应一个SYN ACK时,扫描仪的ACK,以及一个新的连接被建立。

在code没有抱怨什么,但后来我TcpLister / TcpClient的似乎永远不会接收任何更多的数据,甚至当它接收并获得确认为在Wireshark中看到的。看似的TcpListener和处理程序仍然在等待数据的旧的连接?我是新来这个层次的网络编程(和相对较新的C#本身),所以肯定指出,如果我失去了一些东西明显。

服务器的code片断:

公共无效的run()  {    而(!关机)    {      关闭= FALSE; //复位      listenerServer =新的TcpListener(IPAddress.Any,scanner.Address.Port);      尝试      {        listenerServer.Start();        TcpClient的处理程序= listenerServer.AcceptTcpClient();        而(真)        {          尝试          {            incomingData = NULL;            的DataBuffer =新的字节[256];            的NetworkStream流= handler.GetStream();这里//块            INT I;            而((ⅰ= stream.Read(DataBuffer中,0,dataBuffer.Length))!= 0)            {              incomingData + = Encoding.ASCII.GetString(DataBuffer中,0,I);              INT的startIndex = incomingData.IndexOf(startMarker);              INT endIndex的= incomingData.IndexOf(结束标记);              如果(在startIndex> -1放大器;&安培; endIndex的> -1)              {                字符串serialData = incomingData.Substring(在startIndex + 1,endIndex的 - 在startIndex - 1);                scanner.ProcessDataChange(serialData);              }            }          }          赶上(IOException异常E)          {            //处理SocketExceptions这里...          }          最后          {            handler.Close();          }        }      }      赶上(SocketException E)      {        listenerServer.Stop();        listenerServer = NULL;      }      最后      {        listenerServer.Stop();        listenerServer = NULL;      }    }  }

解决方案

用户 @LB(L. B)民政事务总署回答的问题,但删除了它认为它可能是不相关的。事实上,这是一个很大的问题的答案,所以我在这里重新张贴它。最终,我没有听都正在取得新的连接。 应该L.乙希望重新发布他的答案,我会很乐意接受它。的

的的转播L. b应答

您接受的TcpClient处理器= listenerServer.AcceptTcpClient()只有一个连接;

在第一个连接被关闭,你不接受连接了。你应该把它移动到while循环。

修改

这是不是直接回答你的问题。但我试过跌破code和它工作得很好。如果你愿意,你可以试试。我将在稍后删除这个答案。

无效的run()  {      的TcpListener监听器=新的TcpListener(IPAddress.Any,12345);      listener.Start();     Task.Factory.StartNew(()=>     {         而(真)         {             变种客户= listener.AcceptTcpClient();             Task.Factory.StartNew(()=>处理程序(客户机),TaskCreationOptions.LongRunning);         }     },TaskCreationOptions.LongRunning);  }  无效处理程序(TcpClient的客户端)  {      使用(的NetworkStream流= client.GetStream())      {          VAR的DataBuffer =新的字节[256];          INT I;          而((ⅰ= stream.Read(DataBuffer中,0,dataBuffer.Length))!= 0)          {              //处理数据在这里..              //变种S = Encoding.UTF8.GetString(DataBuffer中,0,I);              //Console.Write(s);          }      }  }

I have an issue where, depending on the startup order of two network devices, I seem to lose the ability to receive data on one end.

The setup is one small server written in C# (.NET 4.0) that listens to a specific port for data coming from an industrial scanner, communicating over TCP. The scanner connects to the server application just fine, and will send small chunks of data (serial numbers) which the server receives and processes. However, restarting (actually, cycling power, doesn't gracefully close its connection) on the scanner causes the server to stop processing data. The order of events, as well as the crucial network traffic that causes problems goes as follows:

             SUCCESS                           FAILURE
     |----------------------|             |----------------------|
     |  SCANNER  |  SERVER  |             |  SCANNER  |  SERVER  |
     |----------------------|             |----------------------|
     |           |   Starts |             |  Starts   |          |
     |   Starts  |          |             |           |  Starts  |
     |    Scan   | Received |             |   Scan    | Received |
     |  Restarts |          |             |  Restarts |          |
     --------(Network)-------             --------(Network)-------
     |    SYN    |          |             |    SYN    |          |
     |           | ACK-123  |             |           | SYN ACK  |
     | RST - 123 |          |             |    ACK    |          |
     |    SYN    |          |             |           |          |
     |           |  SYN ACK |             |           |          |
     |    ACK    |          |             |           |          |
     |----------------------|             |----------------------|  
     |    Scan   | Received |             |    Scan   |  !LOST!  |
     |----------------------|             |----------------------|      

As you can see, in the SUCCESS scenario, after the scanner restart, the server responds to the SYN with an ACK, and the scanner resets the connection because it realizes it is not in the right stream. The server detects this and gracefully handles it. However, in the FAILURE scenario, the server blissfully responds with a SYN ACK, scanner ACKs, and a new connection is established.

The code doesn't complain about anything, but then my TcpLister/TcpClient never seems to receive any more data, even when it is received and ACKed as seen in Wireshark. Seemingly the TcpListener and handler are still waiting on the old connection for data? I'm new to this level network programming (and relatively new to C# itself), so definitely point out if I'm missing something obvious.

Code snippet of the server:

public void Run() 
 {
   while (!shutdown)
   {
     shutdown = false; // Reset
     listenerServer = new TcpListener(IPAddress.Any, scanner.Address.Port);

     try
     {
       listenerServer.Start();
       TcpClient handler = listenerServer.AcceptTcpClient();

       while (true)
       {
         try
         {
           incomingData = null;
           dataBuffer = new Byte[256];
           NetworkStream stream = handler.GetStream(); // blocks here
           int i;

           while ((i = stream.Read(dataBuffer, 0, dataBuffer.Length)) != 0)
           {
             incomingData += Encoding.ASCII.GetString(dataBuffer, 0, i);
             int startIndex = incomingData.IndexOf(startMarker);
             int endIndex = incomingData.IndexOf(endMarker);
             if (startIndex > -1 && endIndex > -1)
             {
               string serialData = incomingData.Substring(startIndex + 1, endIndex - startIndex - 1);
               scanner.ProcessDataChange(serialData);
             }
           }
         }
         catch (IOException e)
         {
           // Deals with SocketExceptions here...
         }
         finally
         {
           handler.Close();
         }
       }
     }
     catch (SocketException e)
     {
       listenerServer.Stop();
       listenerServer = null;
     }
     finally
     {
       listenerServer.Stop();
       listenerServer = null;
     }
   }
 }

解决方案

User @LB (L. B) had answered a question, but deleted it thinking it may have been irrelevant. In fact, it was a great answer to the question, and so I am reposting it here. In the end, I wasn't listening to the new connections that were being made. Should L. B wish to repost his answer I'll gladly accept it.

Repost of L. B's answer

You accept only one connection with TcpClient handler = listenerServer.AcceptTcpClient();

When the first connection is closed you don't accept connections anymore. You should move it into the while loop.

EDIT

This is not a direct answer to you question. But I tried the below code and it works well. If you want, you can try it. I'll remove this answer later.

 void Run()
 {
     TcpListener listener = new TcpListener(IPAddress.Any, 12345);
     listener.Start();

    Task.Factory.StartNew(() =>
    {
        while (true)
        {
            var client = listener.AcceptTcpClient();
            Task.Factory.StartNew(() => Handler(client), TaskCreationOptions.LongRunning);
        }
    }, TaskCreationOptions.LongRunning);
 }

 void Handler(TcpClient client)
 {
     using (NetworkStream stream = client.GetStream())
     {
         var dataBuffer = new Byte[256];
         int i;
         while ((i = stream.Read(dataBuffer, 0, dataBuffer.Length)) != 0)
         {
             // Processes data here..
             //var s = Encoding.UTF8.GetString(dataBuffer, 0, i);
             //Console.Write(s);

         }
     }
 }