2

約30台の車のモデムからメッセージをリッスンするアプリケーションがあります。TcpListenerを使用して、次のようなサーバーコードを実装しました(エラー処理は省略されています)。

...
listener.Start()
...
void 
BeginAcceptTcpClient()
{
    if(listener.Server.IsBound) {
        listener.BeginAcceptTcpClient(TcpClientAccepted, null);
    }
}

void 
TcpClientAccepted(IAsyncResult ar)
{
    var buffer = new byte[bufferSize];

    BeginAcceptTcpClient();
    using(var client = EndAcceptTcpClient(ar)) {
    using(var stream = client.GetStream()) {
        var count   = 0;
        while((count = stream.Read(buffer, total, bufferSize - total)) > 0) {
            total += count;
        }
    }
    DoSomething(buffer)
}

私はメッセージを正しく受け取ります、私の問題は切断にあります。12時間ごとにモデムはリセットされ、新しいIPアドレスを取得しますが、サーバーは引き続き古い接続をアクティブに保ちます(tcpviewでESTABLISHEDとしてマークされます)。古い接続のタイムアウトを設定する方法はありますか?TcpClientを閉じることでTCP接続が閉じられたと思いました(そしてそれが私のローカルテストで起こります)、私が間違っていることは何ですか?

4

1 に答える 1

1

私は実際にコードサンプルに少し混乱しています-質問はこれらの質問がかなり長い間開かれていることを示唆していますが、コードは非常に短いバーストでより一般的です。長時間実行される接続の場合、同期APIではなく非同期APIの1つがここに表示されると思います。

トレースなしで死ぬソケットは非常に一般的です。特に、シャットダウンを検出する必要のある多数の中間デバイスとともに配布される場合はそうです。特にワイヤレスネットワークは、ソケットを人為的に存続させようとすることがあります。これは、デバイスが毎回すべての接続を切断することを望まないため、ワイヤレス接続が一時的に失われることが非常に一般的だからです。

そのため、接続に何らかのハートビートを実装することは非常に一般的です。これにより、誰がまだ実際に生きているかを追跡できます。

例として-私はここにWebSocketサーバーを持っています。これは理論上、正常なシャットダウン(閉鎖を示す特定のシーケンスを介して)と非優雅なソケットの閉鎖(予期せずに接続を終了する)の両方を処理します-しかし、私が見た19k接続の過去1時間ほどで、70人がどちらにも当たらずに死亡しました。その代わりに、私は(遅い)心拍に対して活動を追跡し、彼らがあまりにも長い間応答しない場合はそれらを殺します。

再タイムアウト; を試すことはできますがReceiveTimeout、それは通常、トラフィックに大きなギャップが生じることを期待していない場合にのみ役立ちます。

于 2012-03-01T12:15:21.190 に答える