据我所知,一旦调用
如果我们通过一次发送1,000个连接来对我们的
我们调用
这是我们正在使用的
我认为答案与使用
我们提出的一个想法是调用
Start()
,TcpListener
将排队连接。每次调用AcceptTcpClient
(或BeginAcceptTcpClient
)时,它将从队列中出列一个项目。如果我们通过一次发送1,000个连接来对我们的
TcpListener
应用程序进行负载测试,则队列的构建速度远远快于我们清除它的速度,最终导致客户端超时,因为它没有得到响应,因为它的连接仍然在队列中。但是,服务器似乎没有太大的压力,我们的应用程序没有消耗太多的CPU时间,机器上的其他监视资源也没有流汗。感觉我们现在运行效率不高。我们调用
BeginAcceptTcpListener
,然后立即交给ThreadPool
线程实际完成工作,然后再次调用BeginAcceptTcpClient
。涉及的工作似乎不会给机器带来任何压力,基本上只是3秒的睡眠,然后是字典查找,然后是100字节写入TcpClient
的流。这是我们正在使用的
TcpListener
代码: // Thread signal.
private static ManualResetEvent tcpClientConnected = new ManualResetEvent(false);
public void DoBeginAcceptTcpClient(TcpListener listener)
{
// Set the event to nonsignaled state.
tcpClientConnected.Reset();
listener.BeginAcceptTcpClient(
new AsyncCallback(DoAcceptTcpClientCallback),
listener);
// Wait for signal
tcpClientConnected.WaitOne();
}
public void DoAcceptTcpClientCallback(IAsyncResult ar)
{
// Get the listener that handles the client request, and the TcpClient
TcpListener listener = (TcpListener)ar.AsyncState;
TcpClient client = listener.EndAcceptTcpClient(ar);
if (inProduction)
ThreadPool.QueueUserWorkItem(state => HandleTcpRequest(client, serverCertificate)); // With SSL
else
ThreadPool.QueueUserWorkItem(state => HandleTcpRequest(client)); // Without SSL
// Signal the calling thread to continue.
tcpClientConnected.Set();
}
public void Start()
{
currentHandledRequests = 0;
tcpListener = new TcpListener(IPAddress.Any, 10000);
try
{
tcpListener.Start();
while (true)
DoBeginAcceptTcpClient(tcpListener);
}
catch (SocketException)
{
// The TcpListener is shutting down, exit gracefully
CheckBuffer();
return;
}
}
我认为答案与使用
Sockets
而不是TcpListener
有关,或者至少要使用TcpListener.AcceptSocket
,但我想知道如何做到这一点?我们提出的一个想法是调用
AcceptTcpClient
并立即将TcpClient
Enqueue
到多个Queue<TcpClient>
对象之一中。这样,我们可以在单独的线程上轮询这些队列(每个线程一个队列),而不会遇到可能在等待其他Dequeue
操作时阻止线程的监视器。然后,每个队列线程都可以使用ThreadPool.QueueUserWorkItem
在ThreadPool
线程中完成工作,然后继续出队其队列中的下一个TcpClient
。您是否推荐此方法,或者我们的问题在于我们正在使用TcpListener
,无论快速出队多少次也无法解决?