2つのネットワークデバイスの起動順序によっては、一方の端でデータを受信できなくなるように見えるという問題があります。
セットアップは、C#(.NET 4.0)で記述された1つの小さなサーバーであり、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で正常に応答し、新しい接続が確立されます。
コードは何も文句を言いませんが、Wiresharkで見られるように、データが受信されてACKされた場合でも、TcpLister/TcpClientはそれ以上データを受信しないようです。どうやら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;
}
}
}