TCP 服务器应用程序中异步访问的集合类

Posted

技术标签:

【中文标题】TCP 服务器应用程序中异步访问的集合类【英文标题】:Collection class for asynchronous access in a TCP server application 【发布时间】:2012-07-02 11:55:04 【问题描述】:

我正在处理一个 TCP 服务器项目。 它异步监听指定端口的连接,接受新连接并开始等待来自它们的数据。 每个新客户端在连接时都会发送它的 ID,这样我就知道哪个套接字属于哪个客户端。

最少 100000 个客户端将同时连接到服务器。

问题是我应该如何存储这些客户端?

class Client

    public Socket Socket  get; set; 
    public int ID  get; set; 

List<Client> 之类的东西肯定会中断,因为List<T> 不是线程安全类型。我应该在客户端连接到服务器时将其添加到列表中,当连接丢失时将其从列表中删除。例如,我还需要能够向 ID 为 5 的客户端发送消息,并且在异步环境中迭代 List<T> 是一个糟糕的主意。我认为每次我需要与集合交互时锁定同步根对性能没有任何好处。

那么,我应该使用什么来提高性能?

编辑:我使用 .NET 4

【问题讨论】:

【参考方案1】:

我会使用以 ID 作为键的线程安全字典。如果您使用的是 .net 4,则可以使用 System.Collections.Concurrent.ConcurrentDictionary - 如果不是,您可以自己滚动或查看此 url 以获得使用读写器锁的好方法

http://devplanet.com/blogs/brianr/archive/2008/09/26/thread-safe-dictionary-in-net.aspx

【讨论】:

【参考方案2】:

您应该使用Dictionary<int, Client> 而不是List<Client>。这样,您可以使用单行代码访问任何 id 的客户端,例如

 Dictionary<int, Client> connected = new Dictionary<int, Client>();
 Client cc = connected[5];
 byte[] data = new byte[100]; // any data here
 cc.SendData(data);

【讨论】:

请记住,当您遍历集合时,如果添加或删除了某些内容,则会抛出异常,说明集合已被修改。 如果您想要线程安全并且不想自己锁定,请考虑使用 ConcurrentDictionary。 我不需要迭代它,只要我可以使用它的密钥/ID 获取客户端。 (不过,我不知道索引器是如何获取它的。它不会迭代吗?)。添加和删​​除项目也是如此,服务器不断地监听新的连接。您对此有何建议?使用锁? @weismat,我也看到了 Toby 的回答,但是当 Waqar 说标准字典是线程安全的时,我想知道它的线程安全性如何,然后再决定哪个更好。 你还应该考虑 ConcurrentDictionary 通用字典在您的场景中绝对不是线程安全的 - 您几乎肯定会发现在您为字典编制索引以发送一个条目的同时添加/删除条目的情况给客户的消息。这是一篇关于字典线程安全的 msdn 博客:blogs.msdn.com/b/kimhamil/archive/2008/03/08/… 如您所见,如果您的字典在调用 TryGetValue 的同时重新调整大小,则 TryGet 可能返回错误的值,您可以发送消息到错误的客户!

以上是关于TCP 服务器应用程序中异步访问的集合类的主要内容,如果未能解决你的问题,请参考以下文章

在异步 TCP 服务器的上下文中从 N 头访问数据时的线程安全

Python使用socketserver建立一个异步TCP服务器

ESP32/ESP8266TCP异步通讯点灯控制示例程序

集合多线程网络编程JDBC连接池反射综合应用

使用 Boost Asio 在 TCP 套接字上执行异步写入操作

IIS异步控制器操作中的互斥锁实现?