Linux套接字文件描述符通常适用于散列
问题描述:
我正在编程一个Linux多用户服务器,并且每个接受的连接返回一个包含该连接的套接字文件描述符的int
。我还有一个对应于每个连接的对象UserConnection
。我使用散列表(C++ STL unordered_map<int, UserConnection>
)来存储套接字文件描述符(键)和对象(值)的键值对。Linux套接字文件描述符通常适用于散列
把套接字文件描述符作为关键字放在散列表中是否安全? Linux的套接字号分配有没有任何模式可能不适用于散列函数?
答
的manual page for open(2)显式地规定,最低未使用的文件描述符被分配到新的文件描述符:
成功调用返回的文件描述符将成为 编号最低的文件描述符目前没有开放的处理。
似乎从socket(2)
错过了类似的措词,但我认为这是一个相当安全的假设 - 这同样适用于套接字。
然后,创建套接字将导致单调增加文件描述符,为新的套接字,这将在第一次机会将被重用。因此,这是哈希的理想用例。
假设您在套接字关闭时移除了键(理想情况下,就在之前,为了避免竞争条件,如果关闭套接字并且另一个线程使用相同的fd打开套接字),我没有看到任何明显的问题。 – ShadowRanger
良好的电话:谢谢!我更改了UserConnection,并将套接字移到了析构函数中,这样只有在ConnectionManager类的关键字上调用unordered_map :: erase时才能完成。 – Anton
您也可以预先将用于描述符的整数值表格构建为散列。没有必要在飞行中对所有这些进行哈希。它也好像一个简单的稀疏矢量也能很好地工作。一个更有趣的应用可能是......一个独特的连接是4元组{源IP,源端口,目的IP,目的端口}。使用散列表并消化4元组可能更适合参与。最后,您可能需要键入哈希以避免潜在的DoS。我相信[内核切换到SipHash](https://lwn.net/Articles/711167/)这样的应用程序。 – jww