当前位置: 首页 > 编程语言 > C#

TcpListener:如何在等待AcceptTcpClientAsync()时停止监听?

时间:2023-04-11 00:23:30 C#

TcpListener:如何在等待AcceptTcpClientAsync()时停止监听?我不知道如何在异步方法等待传入连接时正确关闭TcpListener。我在SO上找到了这段代码,代码如下:publicclassServer{privateTcpListener_Server;私人布尔_Active;publicServer(){_Server=newTcpListener(IPAddress.Any,5555);}publicasyncvoidStartListening(){_Active=true;_Server.Start();等待接受连接();}publicvoidStopListening(){_Active=false;_Server.Stop();}privateasyncTaskAcceptConnections(){while(_Active){varclient=await_Server.AcceptTcpClientAsync();DoStuffWithClient(客户端);}}privatevoidDoStuffWithClient(TcpClientclient){//...}}Main:staticvoidMain(string[]args){varserver=newServer();服务器.StartListening();线程.睡眠(5000);服务器.StopListening();控制台.Read();}此行有一个异常awaitAcceptConnections();当我调用Server.StopListening()时,对象被删除。所以我的问题是,如何取消AcceptTcpClientAsync()以正确关闭TcpListener。虽然有一个基于StephenToub的博客文章的相当复杂的解决方案,但使用内置.NETAPI的解决方案更简单:varcancellation=newCancellationTokenSource();awaitTask.Run(()=>listener.AcceptTcpClientAsync(),cancellation.Token);//在另一个线程中的某处cancellation.Cancel();此解决方案不会终止挂起的接受调用。但是其他解决方案也不这样做,这个至少更短。更新:一个更完整的示例,显示取消后应该发生什么:varcancellation=newCancellationTokenSource();varlistener=newTcpListener(IPAddress.Any,5555);监听器.Start();try{while(true){varclient=awaitTask.Run(()=>listener.AcceptTcpClientAsync(),cancellation.Token);//使用客户端,也将CancellationToken传递给其他阻塞方法}}finally{listener.Stop();}//在另一个线程中的某处cancellation.Cancel();更新2:Task.Run仅在任务启动时检查取消标记。为了加速接受循环的终止,您可能希望注册取消:cancellation.Token.Register(()=>listener.Stop());定义此扩展方法:publicstaticclassExtensions{publicstaticasyncTaskAcceptTcpClientAsync(thisTcpListenerlistener,CancellationTokentoken){}catch(Exceptionex)when(token.IsCancellationRequested){thrownewOperationCanceledException("在等待TCP客户端连接时请求取消。",ex}at);在使用扩展方法接受客户端连接之前:token.Register(()=>listener.Stop());由于这里没有合适的工作示例,这里有一个:假设您同时拥有cancellationToken和tcpListener,那么您可以执行以下操作:等待tcpListener.AcceptTcpClientAsync();//…进行…}catch(InvalidOperationException){//tcpListener.Start没有被调用(错误!)//或者在我们开始接受之前取消了CancellationToken(给出InvalidOperationException),//或者消除ionToken在我们开始接受之后被取消(给出一个ObjectDisposedException)。////在后两种情况下,我们应该显示取消//异常,否则重新抛出原始异常。cancellationToken.ThrowIfCancellationRequested();}扔;为我工作:创建一个本地虚拟客户端以连接到侦听器,并在接受连接后,不要执行另一个异步接受(使用活动标志)//这是接受回调知道不是_Active=false;TcpClientdummyClient=newTcpClient();dummyClient.Connect(m_listener.LocalEndpoint作为IPEndPoint);dummyClient.Close();这可能是一个hack,但它似乎比其他选项更漂亮:)CallingStopListening(configsocket)是正确的。只是吞下那个特定的错误。您无法避免这种情况,因为无论如何您都需要停止挂起的呼叫。如果不是,则套接字已泄漏,挂起的异步IO和端口仍在使用中。在不断监听新的连接客户端时,我使用了以下解决方案:publicasyncTaskListenAsync(IPEndPointendPoint,CancellationTokencancellationToken){监听器.Start();//Stop()通常会使AcceptSocketAsync()抛出ObjectDisposedException。取消令牌。Register(()=>listener.Stop());//持续监听新客户端连接。尝试{while(true){cancellationToken.ThrowIfCancellationRequested();套接字clientSocket=等待列表.AcceptSocketAsync();}}catch(OperationCanceledException){抛出;}catch(Exception){cancellationToken.ThrowIfCancellationRequested();我对异步编程很陌生,所以请原谅我对这种方法有疑问——我很高兴看到它指出来学习它!取消令牌有一个委托,您可以使用它来停止服务器。当服务器停止时,任何监听连接调用都会抛出套接字异常。请参考以下代码:以上为C#学习教程:TcpListener:HowtostoplisteningwhilewaitingforAcceptTcpClientAsync()?分享的所有内容,如果对你有用,需要进一步了解C#学习教程,希望你多多关注——publicclassTcpListenerWrapper{//base.Activepublic就不需要helper类了,来吧微软。..privateclassTcpListenerActive:TcpListener,IDisposable{publicTcpListenerActive(IPEndPointlocalEP):base(localEP){}publicTcpListenerActive(IPAddresslocaladdr,intport):base(localaddr,port){}publicvoidDispose(){Stop();}publicnewboolActive=>base.Active;}privateTcpListenerActiveserverpublicasyncTaskStartAsync(intport,CancellationTokentoken){if(server!=null){server.Stop();}server=newTcpListenerActive(IPAddress.Any,port);server.Start(maxConnectionCount);token.Register(()=>server.Stop());while(server.Active){try{awaitProcessConnection();}赶上(异常前){控制台。写行(例如);}}}privateasyncTaskProcessConnection(){使用(TcpClientclient=awaitserver.AcceptTcpClientAsync()){//处理连接}}}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: