0

実際の問題領域を覆い隠すことなく、できるだけ多くのコードを省略しようとしました。完全なコードを表示する必要がある場合は、お知らせください。

そのため、データベース接続を軽減し、単一ノードからのすべてのインバウンド データベース リクエストを処理する非常にシンプルな TCP アプリケーションを構築しました。このコードは、約 200,000 の接続 (要求と応答) を処理し、その後、要求を受信すると BinaryFormatter.Deserialize メソッドでランダムにどこかでハングします。なぜこれが起こっているのか、誰にも考えがありますか?

例外は生成されず、無期限にハングします。

サーバーコード:

public class TCPServer
{
    /// <summary>
    /// The listener which listens for inbou nd requests.
    /// </summary>
    private TcpListener _tcpListener;

    /// <summary>
    /// The thread the inbound listener operates on.
    /// </summary>
    private Thread _listenerThread;

    private static object       _lockObject = new object();

    public TCPServer()
    {
        _tcpListener = new TcpListener( IPAddress.Any, 19926 );
        _listenerThread = new Thread( new ThreadStart( ListenForClients ) );
        _listenerThread.Start();
        //Get the server's ip so that the server can connect to its own database.
        DAL.ServerIP = GetLocalIP();
    }

    /// <summary>
    /// Waits for new clients to communicate.  When a new client request is heard,
    /// the connection is given its own processing thread.
    /// </summary>
    private void ListenForClients()
    {
        _tcpListener.Start();

        while( true )
        {
            TcpClient client = _tcpListener.AcceptTcpClient();
            Thread clientThread = new Thread( delegate()
            {
                //Pass in the Current Thread Number so that it can be locked in
                HandleClientComm( client );
            } );
            clientThread.Start();
        }
    }

    /// <summary>
    /// Handles all of the connections for requests.  After a request is recieved, the
    /// TcpClient is passed to this method in its own thread for processing.  This is
    /// where all of the magic happens.  Here we deserialize the NetworkStream and 
    /// use the resulting object to determine which request the client is making, and
    /// respond appropriately.
    /// </summary>
    /// <param name="client"></param>
    private void HandleClientComm( object client )
    {
        lock( _lockObject )
        {
            Response response = new Response();
            TcpClient tcpClient = (TcpClient) client;
            try
            {   
                NetworkStream clientStream = tcpClient.GetStream();

                IFormatter formatter = new BinaryFormatter();
                object result = formatter.Deserialize( clientStream );

                //Determine which type of request this is
                Response response = new Response();

                //Code Omitted, Determine which type of request, and use that to formulate the response.

                RespondToClient( tcpClient, response );
            }
            catch( Exception e )
            {
                response = new Response();
                response.ErrorMessage = e.ToString();
                RespondToClient( tcpClient, response );
            } 
        }
    }

    private void RespondToClient( TcpClient client, Response response )
    {
        try
        {
            IFormatter formatter = new BinaryFormatter();
            NetworkStream stream = client.GetStream();
            formatter.Serialize( stream, response );

            stream.Close();
            client.Close();
        }
        catch( Exception e )
        {
            throw e;
        }
    }
}

クライアントコード:

public class TCPClient
{
    public static string ServerIP = "192.168.2.200";

    private static Response RequestTCP<T>(T request)
    {
        try
        {
            TcpClient client = new TcpClient();
            IPEndPoint serverEndPoint = new IPEndPoint( IPAddress.Parse( ServerIP ), 19926 );

            client.Connect( serverEndPoint );
            NetworkStream stream = client.GetStream();
            IFormatter formatter = new BinaryFormatter();

            formatter.Serialize( stream, request );
            Response response = ( Response ) formatter.Deserialize( stream );
            return response;
        }
        catch( Exception e )
        {
            return new Response( "Error with the Response: " + e.ToString() );
        }
    }
}
4

0 に答える 0