1

しばらくの間解決しようとしていた問題がありますが、まだ成功していません。メッセージを同期的に交換することで機能する単純なサーバークライアントアプリがあります。

ここに関連コードがあります。

ソケットの作成:

Socket sender;

IPAddress ipAddress = IPAddress.Parse(remoteHost);                
IPEndPoint remoteEP = new IPEndPoint(ipAddress, remotePort);
sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sender.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
sender.ReceiveTimeout = 5000;
sender.Connect(remoteEP);    

データ受信中:

try {
if (!sender.Connected)
    Reconnect();
int bytesRec = sender.Receive(readBuffer);

if (bytesRec == 0)
{
   //warning 0 bytes received
}
return Encoding.ASCII.GetString(readBuffer, 0, bytesRec);
}
catch (SocketException se)
{
   //print se.ErrorCode
   throw;
}

データの送信:

try {
if (!sender.Connected)
    Reconnect();

byte[] msg = Encoding.ASCII.GetBytes(sendMessage + "\0");

int bytesSent = sender.Send(msg);

return true;
}
catch (SocketException se)
{
   //print se.ErrorCode
   throw;
}

再接続コード:

if (sender != null)
{
    if (sender.Connected)
    {
        sender.Shutdown(SocketShutdown.Both);
        sender.Disconnect(true);
    }

    sender.Close();

    IPAddress ipAddress = IPAddress.Parse(RemoteHost);
    IPEndPoint remoteEP = new IPEndPoint(ipAddress, RemotePort);
    sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);
    sender.ReceiveTimeout = 5000;
    sender.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

    sender.Connect(remoteEP);
}

何が起こっているかは次のとおりです。

データの受信中に、タイムアウトを意味する 10060 エラー コードが表示されます。ということで再接続を試みます。次に、次の例外とともに、しばらくの間同じエラー コードをスローし続けます: 接続先が一定時間後に適切に応答しなかったために接続の試行が失敗したか、接続されたホストが nnnn:x に応答しなかったために確立された接続が失敗しました。

その後、最終的に「再接続」に成功しますが、0 バイトを受信します。ということで、データを送ってみる。WSAECONNABORTED 10053 エラーで失敗し始めます。もう一度再接続を試みます。10053 エラーで続き、0 バイトを受信します。回復することはありません。

そのため、アプリを閉じて再度起動しましたが、接続できません。サーバーログには、開いている接続が多すぎると書かれています。問題は、クライアントが切断されたことをサーバーが認識しないことです...

私はここで少し迷っています。助けてください!

4

1 に答える 1

2

あなたの問題を解決すべきだと思うのは、以下のように変更することです:

受信バイトがなく、Socket.ReceiveTimeout と Socket.SendTimeout を Socker サーバー/クライアントで必要な適切な値に設定している場合 (これを使用する目的については手動で確認してください。通常は 1 ~ 5 分です)。次に、ソケットを切断し、新しい接続を作成します。RSTとして示されているように、相手側からのリセットまたは孤立した接続 (TCP プロトコル用語) のようなもの、つまり再接続するように指示しています。

データを受信

try
{
    if (!sender.Connected)
       Reconnect();

    int bytesRec = sender.Receive(readBuffer);    
    if (bytesRec == 0)
    {
        //warning 0 bytes received and some logging
        // Reconnect code here or function calling to reconnect
        Reconnect();
    }
    return Encoding.ASCII.GetString(readBuffer, 0, bytesRec);
}
catch (SocketException se)
{
   //print se.ErrorCode
   throw;
}
于 2013-03-05T12:41:39.297 に答える