0

Socketsを使用してサーバー側のコードを記述しましたが、正常に機能していますが、このシナリオの処理方法がわからないという問題が1つあります。クライアントが切断要求を送信せずにアプリケーションを閉じると、サーバー側のプログラムがクラッシュします。これを回避するにはどうすればよいですか?ソケットプログラミングは初めてです。

private void OnReceive(IAsyncResult result)
{
    try
    {
        Socket clientSocket = (Socket)result.AsyncState;
        clientSocket.EndReceive(result);

        command = responseMessage = string.Empty;
        command = ByteToString(receviedData);
        receviedData = new byte[30];

        if (command=="Connect")
        {
            ClientInfo clientInfo = new ClientInfo();
            clientInfo.socket = clientSocket;
            clientInfo.IP = clientSocket.RemoteEndPoint.ToString();
            connectedClients.Add(clientInfo);
            responseMessage = "Connection established...";
        }
        else if (command=="Disconnect")
        {
            for (int i = 0; i < connectedClients.Count; i++)
            {
                if (connectedClients[i].socket == clientSocket)
                {
                    connectedClients.RemoveAt(i);
                    break;
                }
            }
            clientSocket.Close();
        }
        else
        {
            responseMessage = "Error";
        }

        byte[] responseStatus = StringToByte(responseMessage);
        for (int i = 0; i < connectedClients.Count; i++)
        {
            if (connectedClients[i].socket==clientSocket)
            {
                connectedClients[i].socket.BeginSend(responseStatus, 0, responseStatus.Length,SocketFlags.None, new AsyncCallback(OnSend), connectedClients[i].socket);
                break;
            }
        }

    }
    catch(Exception ex)
    {
      throw new Exception(ex.Message);
    }
}
4

2 に答える 2

2

catchメソッドのブロックで例外をスローしたため、アプリケーションがクラッシュします。

アプリケーションをクラッシュさせたくない場合は、ブロックthrow new Exception(ex.Message);から行を削除する必要があります。catchエラーを処理し、アプリケーションを安全な状態に正常に復元するコードに置き換えます。clientSocketあなたのコードを読むことから、これはからを削除することによって行われるべきですconnectedClients

次に、throw;の代わりに使用することをお勧めしthrow new Exception(ex.Message);ます。throw;元の例外オブジェクトを再スローするため、ソフトウェアのデバッグに役立つスタックトレースやその他の重要な情報が保持されます。を使用new Exception("Message")すると、現在のスタックトレースで完全に新しい例外オブジェクトが作成されます。

private void OnReceive(IAsyncResult result)
{
    try
    {
        Socket clientSocket = (Socket)result.AsyncState;
        clientSocket.EndReceive(result);

        command = responseMessage = string.Empty;
        command = ByteToString(receviedData);
        receviedData = new byte[30];

        if (command=="Connect")
        {
            ClientInfo clientInfo = new ClientInfo() {
               socket = clientSocket,
               IP = clientSocket.RemoteEndPoint.ToString(),
               }; 
            connectedClients.Add(clientInfo);
            responseMessage = "Connection established...";
        }
        else if (command=="Disconnect")
        {
            removeClientInfo(clientSocket);
            clientSocket.Close();
        }
        else
        {
            responseMessage = "Error";
        }

        byte[] responseStatus = StringToByte(responseMessage);
        for (int i = 0; i < connectedClients.Count; i++)
        {
            if (connectedClients[i].socket==clientSocket)
            {
                connectedClients[i].socket.BeginSend(responseStatus, 0, responseStatus.Length,SocketFlags.None, new AsyncCallback(OnSend), connectedClients[i].socket);
                break;
            }
        }

    }
    catch(Exception ex)
    {
      // add error handling and gracefully recover
      // caution: The way done here, might work, but it smells :-/
      removeClientInfo((Socket)result.AsyncState);
      ((Socket)result.AsyncState).Close();
    }
}

/// removes the client info from the connectedClients enumerable
private void removeClientInfo(Socket socket)
{
    for (int i = 0; i < connectedClients.Count; i++)
    {
        if (connectedClients[i].socket == socket)
        {
            connectedClients.RemoveAt(i);
            break;
        }
    }
}
于 2013-01-12T08:45:08.907 に答える
1

ブロック内で新しい例外をスローしてcatchいますが、ロギングなどを実行しない限り、あまり意味がありません。次のようにキャッチブロックを変更します。

catch(SocketException)
{ 
}

また、から返された読み取りバイト数を確認する必要がありますEndReceive。ゼロバイトを受け取った場合、それはクライアントが接続をシャットダウンしたことを意味します。

int numReceived = clientSocket.EndReceive(result);
if(numReceived == 0)
{
    //client has shutdown the connection
}
于 2013-01-12T08:47:51.740 に答える