【问题标题】:TcpListener/TcpClient stops processing data under certain circumstancesTcpListener/TcpClient 在某些情况下会停止处理数据
【发布时间】:2012-11-15 19:34:35
【问题描述】:

我有一个问题,根据两个网络设备的启动顺序,我似乎失去了一端接收数据的能力。

该设置是一个用 C# (.NET 4.0) 编写的小型服务器,它侦听特定端口以获取来自工业扫描仪的数据,并通过 TCP 进行通信。扫描器可以很好地连接到服务器应用程序,并将发送服务器接收和处理的小块数据(序列号)。但是,在扫描仪上重新启动(实际上是循环电源,不会正常关闭其连接)会导致服务器停止处理数据。事件的顺序以及导致问题的关键网络流量如下:

             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!  |
     |----------------------|             |----------------------|      

如您所见,在 SUCCESS 场景中,扫描器重新启动后,服务器以 ACK 响应 SYN,扫描器重置连接,因为它意识到它不在正确的流中。服务器检测到这一点并优雅地处理它。但是,在 FAILURE 场景中,服务器会以 SYN ACK、扫描仪 ACK 响应并建立新的连接。

代码没有抱怨任何事情,但是我的 TcpLister/TcpClient 似乎再也没有收到任何数据,即使在 Wireshark 中看到它被接收和确认时也是如此。似乎 TcpListener 和处理程序仍在等待旧连接获取数据?我是这个级别的网络编程的新手(并且对 C# 本身相对较新),所以如果我遗漏了一些明显的东西,请务必指出。

服务器的代码sn-p:

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;
     }
   }
 }

【问题讨论】:

    标签: c# .net networking tcp tcpclient


    【解决方案1】:

    用户@LB (L. B) 回答了一个问题,但认为它可能无关紧要而将其删除。事实上,这是对这个问题的一个很好的答案,所以我在这里重新发布它。最后,我没有听到正在建立的新联系。 如果 L.B 希望转发他的答案,我很乐意接受。

    转发 L.B 的回答

    你只接受一个与 TcpClient handler = listenerServer.AcceptTcpClient(); 的连接

    当第一个连接关闭时,您不再接受连接。你应该把它移到while循环中。

    编辑

    这不是您问题的直接答案。但我尝试了下面的代码,它运行良好。如果你愿意,你可以试试。我稍后会删除这个答案。

     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);
    
             }
         }
     }
    

    【讨论】:

      【解决方案2】:

      这类事情的常见原因是希望保留 tcp 发送和接收边界。即您发送一个块并期望在服务器上接收相同的块。这不能保证会发生,而且由于您没有显示您的代码,我无法判断您是否依赖它

      【讨论】:

      • Gotchya,有趣的想法。如果有帮助,请在处理代码中添加。
      • 所以你的代码没问题,但你仍然没有正确的 aceept / 服务器启动代码
      猜你喜欢
      • 1970-01-01
      • 2019-03-27
      • 1970-01-01
      • 1970-01-01
      • 2020-05-05
      • 2017-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多