C#学习教程:使用System.Net.Sockets.Socket.AcceptAsync模型时的堆栈溢出共享.AcceptAsync方法需要处理返回值“false”,以便处理来自同步处理连接的立即可用的SocketAsyncEventArgs状态。Microsoft提供了一些示例(在System.Net.Sockets.SocketAsyncEventArgs类页面中找到),如果存在大量挂起的连接,这些示例可能会导致堆栈溢出,这可以在实现其处理模型的任何系统上被利用。解决此问题的另一个想法是创建一个循环,在Socket.AcceptAsync返回等于false的值的条件下调用处理程序方法,如果该值指示(以允许延迟处理)操作是异步完成的,则中断循环(真的)。但是这种方案也会导致栈溢出漏洞,因为传递给Socket.AcceptAsync的SocketAsyncEventArgs关联的回调在方法的最后调用了Socket.AcceptAsync,同样有一个立即循环,同步accept,connect。如您所见,这是一个非常可靠的问题,我还没有找到一个不涉及System.Threading.ThreadPool并创建大量其他方法和调度处理的好解决方案。据我所知,与Socket.AcceptAsync相关的异步套接字模型需要的不仅仅是MSDN上示例中显示的内容。有没有人有一个干净高效的解决方案来处理从Socket.AcceptAsync同步接受的立即挂起的连接,而无需创建单独的线程来处理连接而不使用递归?我不会使用AcceptAsync,而是使用BeginAccept/EndAccept,并正确实现常见的异步模式,即检查CompletedSynchronously以避免在回调线程中对已完成的操作进行回调。另请参阅AsyncCallBackCompletedSynchronously编辑关于使用AcceptAsync的要求:MSDN文档明确指出不会为同步完成的操作调用回调。这不同于始终调用回调的常见异步模式。如果I/O操作挂起,则返回真。操作完成后,将在e参数上引发SocketAsyncEventArgs.Completed事件。如果I/O操作同步完成,则返回false。不会引发e参数上的SocketAsyncEventArgs.Completed事件,并且可以在方法调用返回以检索操作结果后立即检查作为参数传递的e对象。我目前没有看到循环如何解决堆栈溢出问题。也许您可以更具体地说明导致问题的代码?编辑2:我正在考虑这样的代码(仅AcceptAsync,其余的只是为了一个有效的应用程序来尝试):staticvoidMain(string[]args){SocketlistenSocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);listenSocket.Bind(newIPEndPoint(IPAddress.Loopback,4444));listenSocket.Listen(100);SocketAsyncEventArgse=newSocketAsyncEventArgs();e.Completed+=AcceptCallback;如果(!listenSocket.AcceptAsync(e)){AcceptCallback(listenSocket,e);}Console.ReadKey(true);}privatestaticvoidAcceptCallback(objectsender,SocketAsyncEventArgse){SocketlistenSocket=(Socket)sender;做{尝试{SocketnewSocket=e.接受套接字;Debug.Assert(newSocket!=null);//在这里使用新套接字施展魔法newSocket.Send(Encoding.ASCII.GetBytes("Hellosocket!"));newSocket.Disconnect(false);newSocket.Close();}catch{//在这里处理任何异常;}最后{e.AcceptSocket=null;//启用重用}}while(!listenSocket.AcceptAsync(e));只需更改循环的位置即可解决此问题,而不是从内部递归调用接受处理程序,将代码包装在条件为“!Socket.AcceptAsync(args)”的do-while循环中以防止堆栈溢出。这背后的原因是您利用回调线程处理立即可用的连接,然后再使用异步等待其他连接。它有效地重用了池线程。我很感谢回复,但出于某种原因,他们都没有点击我,并没有真正解决问题。然而,似乎有什么东西激发了我的灵感,让我产生了这个想法。它避免了手动使用ThreadPool类并且不使用递归。当然,如果有人有更好的解决方案甚至替代方案,我会很高兴听到。我没有仔细看,但闻起来这可能有帮助(请参阅“StackDive”部分):http://blogs.msdn.com/b/mjm/archive/2005/05/04/414793.aspxnewSocket.Send(Encoding.ASCII.GetBytes("Hellosocket!"));newSocket.Disconnect(false);newSocket.Close();上面这段代码的问题在于,这将阻止您的下一个接受操作。更好的办法是这样的:以上是C#学习教程:StackOverflow分享的使用System.Net.Sockets.Socket.AcceptAsync模型时的所有内容。如果对大家有用,需要详细了解C#学习教程,希望大家多多关注while(true){if(e.SocketError==SocketError.Success){//ReadEventArgobjectusertokenSocketAsyncEventArgsreadEventArgs=m_readWritePool.Pop();套接字socket=((AsyncUserToken)readEventArgs.UserToken).Socket=e.AcceptSocket;如果(!socket.ReceiveAsync(readEventArgs))ThreadPool.QueueUserWorkItem(newWaitCallback(ProcessReceiveEx),readEventArgs);.}else{HadleBadAccept(e);}e.AcceptSocket=null;m_maxNumberAcceptedClients);Waifit((listenSocket.AcceptAsync(e))break;}本文采集自网络,不代表立场,如涉及侵权请点击右侧联系管理员删除,如有转载,转载请注明出处:
