1

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

该设置是一个用 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# 本身来说相对较新),所以一定要指出我是否遗漏了一些明显的东西。

服务器的代码片段:

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

2 回答 2

2

用户@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);

         }
     }
 }
于 2012-11-15T21:28:15.357 回答
0

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

于 2012-11-15T20:01:38.143 回答