.NET TcpSocket programming

本文关键字:programming TcpSocket NET | 更新日期: 2023-09-27 17:50:19

在。net的多连接环境中接受套接字的正确方法是什么?即使负载很高,下面这些是否足够?

while (true)
{
   //block untill socket accepted
   var socket = tcpListener.AcceptSocket();
   DoStuff(socket) //e.g. spawn thread and read data
}

也就是说,我可以在单个线程中接受套接字,然后在线程/数据流/任何地方处理套接字吗?问题是关于accept部分

.NET TcpSocket programming

您可能需要BeginAccept异步操作而不是同步的Accept。

如果你想处理负载,你肯定不希望每个连接一个线程-同样,你异步方法。

看看反应器或反应器模式,取决于你是否想要阻塞。我将推荐《并发和网络对象模式》这本书。

这应该没问题,但如果负载更高,你可能会考虑使用这个方法的异步版本:BeginAcceptSocket/EndAcceptSocket.

如果你想要性能最好的服务器,BeginAcceptSocket是一个更好的选择。

更重要的是,这些异步操作在底层使用线程池,而在你当前的实现中,你正在创建和销毁大量的线程,这是非常昂贵的。

我认为最好的方法是调用BeginAccept(),并在OnAccept中再次调用BeginAccept。这将为您提供最佳的并发性。

OnAccept应该像这样:

private void OnAccept(IAsyncResult ar)
{
   bool beginAcceptCalled = false;
   try
   {
       //start the listener again
       _listener.BeginAcceptSocket(OnAccept, null);
       beginAcceptCalled = true;
       Socket socket = _listener.EndAcceptSocket(ar);
       //do something with the socket..
   }
   catch (Exception ex)
   {
       if (!beginAcceptCalled)
       {
          //try listening to connections again
          _listener.BeginAcceptSocket(OnAccept, null);
        }
    }
}

这与性能无关。重要的是你如何与每个客户沟通。此处理将比接受套接字消耗更多的CPU。

我将使用BeginAccept/EndAccept为监听套接字 BeginReceive/EndReceive为客户端套接字。

由于我使用异步CTP和DataFlow,当前代码看起来像这样:

private async void WaitForSockets()
{
    var socket = await tcpListener.AcceptSocketAsync();
    WaitForSockets();
    incomingSockets.Post(socket);
}

注意,看起来像递归调用不会导致堆栈溢出或阻塞。它将简单地为一个新的套接字启动一个新的awaiter并退出。