我有一个问题,根据两个网络设备的启动顺序,我似乎失去了在一端接收数据的能力。
该设置是一个用 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;
}
}
}