我试图在不掩盖真正问题区域的情况下尽可能多地省略代码。如果有人需要查看完整代码,请告诉我。
因此,我们构建了一个非常简单的 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() );
}
}
}