C#学习教程:TcpListener排队连接的速度比我清除它们的速度快每次调用AcceptTcpClient(或BeginAcceptTcpClient)时,它都会从队列中取出一个项目。如果我们通过一次向TcpListener应用程序发送1,000个连接来对其进行负载测试,队列的构建速度远远超过我们清除它的速度,导致(最终)客户端超时,因为它没有得到响应,因为它的连接仍在排队.然而,服务器似乎并没有承受太大压力,我们的应用程序没有消耗太多CPU时间,机器上其他受监控的资源也没有出汗。感觉我们现在的运行效率不够高。我们调用BeginAcceptTcpListener,然后立即切换到ThreadPool线程来实际执行工作,然后再次调用BeginAcceptTcpClient。所涉及的工作似乎不会对机器造成任何压力,它基本上只是3秒的睡眠,然后是字典查找,然后是写入TcpClient的100字节流。这是我们使用的TcpListener代码://线程信号。私有静态ManualResetEventtcpClientConnected=newManualResetEvent(false);publicvoidDoBeginAcceptTcpClient(TcpListenerlistener){//将事件设置为无信号状态。tcpClientConnected.Reset();listener.BeginAcceptTcpClient(newAsyncCallback(DoAcceptTcpClientCallback),侦听器);//等待信号tcpClientConnected.WaitOne();}publicvoidDoAcceptTcpClientCallback(IAsyncResultar){//获取处理客户端请求的监听器,TcpClientTcpListenerlistener=(TcpListener)ar.AsyncState;TcpClient客户端=listener.EndAcceptTcpClient(ar);if(inProduction)ThreadPool.QueueUserWorkItem(state=>HandleTcpRequest(client,serverCertificate));//使用SSL否则ThreadPool.QueueUserWorkItem(state=>HandleTcpRequest(client));//没有SSL//通知调用线程继续。tcpClientConnected.Set();}publicvoidStart(){currentHandledRequests=0;tcpListener=新的TcpListener(IPAddress.Any,10000);尝试{tcpListener.Start();while(true)DoBeginAcceptTcpClient(tcpListener);}catch(SocketException){//TcpListener正在关闭,优雅退出CheckBuffer();返回;我假设答案与使用套接字而不是TcpListener或至少是TcpListener.AcceptSocket有关,但我想知道我们将如何做到这一点?我们的一个想法是调用AcceptTcpClient并立即将TcpClient排入多个Queue对象之一,这样我们就可以在不同线程(每个线程一个队列)上轮询这些队列,而无需在等待其他可能阻塞线程的监视器的Dequeue操作时运行。然后,每个队列线程都可以使用ThreadPool.QueueUserWorkItem在ThreadPool线程中完成工作,然后继续使队列中的下一个TcpClient出队。您会推荐这种方法,还是我们正在使用TcpListener并且没有多少快速出列可以解决这个问题?我已经编写了一些直接使用套接字的代码,但我缺乏对1000个客户端执行负载测试的方法。您能否尝试测试此代码与您当前的解决方案相比如何?我对结果非常感兴趣,因为我现在正在构建一个需要接受大量连接的服务器。静态WaitCallbackhandleTcpRequest=newWaitCallback(HandleTcpRequest);staticvoidMain(){vare=newSocketAsyncEventArgs();e.Completed+=newEventHandler(e_Completed);varsocket=newSocket(AddressFamily.InterNetwork,TypeSocketType.Stream,Protocol.Tcp);socket.Bind(newIPEndPoint(IPAddress.Loopback,8181));socket.Listen((int)SocketOptionName.MaxConnections);socket.AcceptAsync(e);Console.WriteLine("--就绪--");控制台.ReadLine();套接字。关闭();}staticvoide_Completed(objectsender,SocketAsyncEventArgse){varsocket=(Socket)sender;ThreadPool.QueueUserWorkItem(handleTcpRequest,e.AcceptSocket);e.AcceptSocket=null;socket.AcceptAsync(e);}staticvoidHandleTcpRequest(objectstate){varsocket=(Socket)state;线程.睡眠(100);//做工作socket.Close();除非我遗漏了什么,否则你正在调用异步的BeingAcceptTcpClient,但你正在调用WaitOne()来等待异步代码完成,这有效地使进程同步。您的代码一次只能接受一个客户。还是我完全疯了?至少,这似乎是大量上下文切换的结果。在其他问题中提到,但我建议在您的tcpListener.Start()方法中使用重载,允许您将积压设置为高于一次预期的最大连接数的数字:publicvoidStart(){currentHandledRequests=0;tcpListener=newTcpListener(IPAddress.Any,10000);尝试{tcpListener.Start(1100);//这是积压参数while(true)DoBeginAcceptTcpClient(tcpListener);}catch(SocketException){//TcpListener正在关闭,优雅退出CheckBuffer();返回;基本上,这个选项设置允许等待Accept被调用的“挂起”TCP连接数。如果您没有足够快地接受连接,并且这个积压填满,TCP连接将自动被拒绝,您甚至无法处理它们。正如其他人所提到的,另一种可能性是加快传入连接的处理速度。但是,即使可以加快接受时间,您仍应将backlog设置为更高的值。只是一个建议:为什么不同步接受客户端(通过使用AcceptTcpClient而不是BeginAcceptTcpClient),然后在新线程上处理客户端?这样,您就不必在接受下一个客户之前等待客户处理。首先要问自己的是“一次合理的1000个连接”。我个人认为您遇到这种情况的可能性很小。您很可能在短时间内发生1000次连接。我有一个用于测试我的服务器框架的TCP测试程序,它在Y批次中总共执行X个连接,每批次之间的间隔为Z毫秒;我个人觉得这个世界比“一次很多”的现实要好。它是免费的,它可能会有所帮助,您可以从这里获取它:http://www.lenholgate.com/blog/2005/11/windows-tcpip-server-performance.html正如其他人所说,添加Listenforbacklogs,processconnectionsfaster,useasynchronousacceptwherepossible...以上是C#学习教程:TcpListenerqueuesconnectionsfasterthanIcanclearthemC#学习教程,希望大家多多关注—本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
