【问题标题】:Create multiple TCP Connections in C# then wait for data在 C# 中创建多个 TCP 连接然后等待数据
【发布时间】:2010-03-31 05:57:23
【问题描述】:

我目前正在创建一个 Windows 服务,它将创建到多台机器的 TCP 连接(所有机器上的相同套接字),然后侦听来自这些机器的“事件”。我正在尝试编写代码来创建一个连接,然后生成一个线程来侦听等待来自机器的数据包的连接,然后解码通过的数据包,并根据数据包的有效负载调用一个函数。

问题是我不完全确定如何在 C# 中做到这一点。有没有人有任何有用的建议或链接可以帮助我做到这一点?

提前感谢您的帮助!

【问题讨论】:

  • 查看框架中的 IHttpAsyncListener。它可能会为您完成很多工作。

标签: c# asynchronous tcp


【解决方案1】:

根据您计划支持多少并发客户端,每个连接的线程架构可能会很快崩溃。原因是,每个线程都需要大量资源。默认情况下,每个 .NET 线程获得 1MB 的堆栈空间,因此每个连接 1MB 加上任何开销。

相反,当支持多个连接的客户端时,通常您将使用非常有效的asynchronous methods (see here also),因为 Windows 将使用“完成端口”,这基本上可以在等待某些事件时释放线程来做其他事情完成。

为此,您可以查看 BeginAccept、BeginReceive、BeginSend 等方法。

一种更简单的方法是在循环中使用 Socket.Select 方法,也可以避免进行阻塞调用并避免多线程。这允许单个线程服务多个套接字。线程一次只能物理读取或写入单个套接字,但其想法是检查多个套接字的状态,这些套接字可能包含或不包含要读取的数据。

在任何情况下,每个连接一个线程的方法一开始更容易理解,但它确实存在显着的可扩展性问题。我建议先使用同步方法(如 Accept、Receive、Send 等)执行此操作。然后再重构您的代码以使用异步方法,这样您就不会耗尽服务器的内存。

【讨论】:

    【解决方案2】:

    您可以对每个套接字连接进行异步接收并解码来自其他机器的数据以执行您的任务(您可以在此处找到有关异步方法的一些有用信息:http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx)。

    要创建连接,您可以:

    Socket sock = Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    sock.Connect(new IPEndPoint(address, port));
    

    同样,您可以创建多个连接并将引用保存在字典列表中(无论您喜欢哪个)。

    要在套接字上异步接收数据,您可以这样做:

    sock.BeginReceive(buffer, 0, buffer.len, SocketFlags.None, new AsyncCallback(OnDataReceived), null);
    

    接收操作完成时会调用方法OnDataReceived

    OnDataReceived 方法中你必须这样做:

    void OnDataReceived(IAsyncResult result)
    {
       int dataReceived = sock.EndReceive(result);
       //Make sure that dataReceived is equal to amount of data you wanted to receive. If it is
       //less then the data you wanted, you can do synchronous receive to read remaining data.
    
      //When all of the data is recieved, call BeginReceive again to receive more data
    
    
      //... Do your decoding and call the method ...//
    }
    

    希望对你有帮助。

    【讨论】:

      【解决方案3】:

      有一个单独的线程来运行 accept() 来获取新的连接。对于您获得的每个新连接,使用线程池生成一个工作线程。

      【讨论】:

        【解决方案4】:

        我不知道在您的情况下是否可行,但您是否考虑过使用由多台机器调用的 WCF 服务?您可以将其托管在自定义 Windows 服务或 IIS 中。它在等待事件时会消耗很少的资源,而且它的编码比所有那些低级可怕的套接字东西要简单得多。它是自动异步的。您会收到很好的服务消息,而不是需要反序列化和/或解析的数据包。您可以使用任意数量的协议,例如 REST 或二进制。

        您当然需要在发送消息的另一端创建进程。

        只是一个想法......

        干杯

        【讨论】:

          猜你喜欢
          • 2019-09-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多