我一直在脑海中传递一些想法,关于如何在维护KISS的同时,使用IO类型的架构来实际包含大量连接。通过web上的示例,似乎大多数都使用了CONTAINING_RECORD的双/单链表。而且,作为IO服务器的新手(虽然每天都在改进),我也将链表容器用于IO架构。
我的问题是,为什么我不能只构建一个大型数组并使用CONTAINING_RECORD,而不是使用单/双链表进行连接呢?我可以使用STL向量吗?这样行得通吗?此外,还有哪些其他类型的容器最适合与大型IO服务器配合使用。
我正在为我的游戏服务器重写服务器架构(经过多次修改),这一次我想朝着正确的方向前进,因为我不想在不久的将来再次重写它。
感谢您的宝贵时间,并回复。
编辑:目前我的服务器架构是(简而言之):
Main thread listening and accepting -> Pass over the socket into a container.
Worker threads(2-3) grab IO events for the container of sockets.
Worker threads Read/Write Data on that container.主线程和辅助线程都使用链表。我想摆脱这一切。
发布于 2012-09-11 15:21:36
你的“连接列表”可能会从任何位置移除,而不仅仅是末尾。对于std::vector,删除中间的元素是一个O(N)操作,但对于链表,它可以是O(1)。(对于单链表,这不是小事,可能需要一个不方便的API)。
std::map可能是一个有趣的选择,因为它同时提供了元素的O(log N)查找和删除。
发布于 2012-09-11 15:07:19
与所有数据结构一样,它在很大程度上取决于您想要对它做什么。
在之前的工作中,我花了大部分时间在一个巨大的多线程轮询服务器上工作,在它的Windows化身中,它使用了IO完成端口( Solaris后端使用了/dev/ C++,这在几个要点上没有太大的不同)。它将连接相关的数据结构存储在map-like结构中,使用文件描述符作为键值。因此,每当我们在一个连接上得到一个事件时,我们就可以通过IO层传递给我们的描述符来查找它的相关数据结构。新的连接很容易处理-只需在字典中添加一个条目-关闭的连接也可以相当简单地清除。
当然,人们必须小心跨线程访问这些结构和操作顺序-因为IO本质上是有效的,所以操作的顺序至关重要。幸运的是,在您将套接字放回CP之前,IOCP不会为您提供同一套接字的另一个线程上的另一个事件,但Solaris实现还必须保持将文件描述符链接到工作线程的结构,以便确保我们每次只按严格的顺序处理每个套接字的一个事件,并且我们还尝试将套接字的后续事件注入到同一线程中,以避免潜在地将套接字的结构切换到另一个处理器上,这是缓存命中率的灾难。
不过,基本的总结是,我们发现一个设计得当的字典类对于这类事情非常有用。
https://stackoverflow.com/questions/12364139
复制相似问题