为什么Windows上的套接字描述符得到这样的值?

不知道这是否是正确的地方问。
我正在写一个简单的聊天与c + +,其中一个客户端获取套接字值作为开始的昵称。
在Linux套接字只是文件描述符,他们得到他们的3,4,5 …跟随标准input,标准输出,标准错误。
但是我注意到,在Win上,第一个客户端套接字始终得到值192,而其他的则相差20(几乎总是)。
G
所以这里是我的问题,为什么套接字在win平台上获得这样的价值(我的是win7 x64)? 小Google使用没有帮助。
先谢谢了

在POSIX文件中,描述符是整数值,并且要求 open返回一个值“这是当前未打开的最低文件描述符”。 这个规则实际上并不适用于socket但我现在还没有任何不适用于此规则的Unix系统。

但是,Windows不使用POSIX套接字。 它使用Windows套接字,它可以自由地以与POSIX或原始BSD实现不兼容的方式进行定义。 事实上与Windows套接字有很多不兼容的地方。 比你期望的更大的套接字值是一个相对较小的不兼容性,因为这些事情。

使用Windows套接字2所有套接字“文件描述符”实际上是Windows句柄。 这意味着它们可以转换为HANDLE并在许多接受句柄的Windows API函数中用作参数。 这也意味着它们与Windows支持的大量不同类型的对象共享相同的值空间。 像文件,线程,注册表项,信号量等等。 Windows在一个进程的幕后分配了很多这些,Winsock DLL本身使用了相当数量的,所以当你分配你的第一个套接字时,你的进程已经分配了大量的其他句柄。

如果使用Process Explorer查看正在运行的进程并打开“ 显示未命名的句柄和映射”选项,则会看到即使是最简单的进程也有相当多的打开句柄。 如果启用句柄列并使用它来对列表进行排序,则还会看到最低句柄值为4,并且它们都是4的倍数。大多数(如果不是全部是4和最高的4的倍数)清单上的号码将被分配。

虽然他没有解释为什么,Raymond Chen在他的Old New Thing博客中为什么内核句柄总是四的倍数? 确实说是4的倍数保证:

不太为人所知的是内核HANDLE的底部两位总是零; 换句话说,它们的数值总是4的倍数。注意,这仅适用于内核HANDLE; 它不适用于伪句柄或任何其他类型的句柄(USER>句柄,GDI句柄,多媒体句柄…)内核句柄是可以传递给> CloseHandle函数的东西。

底部两位的可用性被掩埋在ntdef.h头文件中: // // Low order two bits of a handle are ignored by the system and available // for use by application code as tag bits. The remaining bits are opaque // and used to store a serial number and table index. // // // Low order two bits of a handle are ignored by the system and available // for use by application code as tag bits. The remaining bits are opaque // and used to store a serial number and table index. //

Mark Russinovich关于推动Windows限制的博客:Handles讨论了一些关于如何在Windows上实现句柄的内幕。 不幸的是,它没有描述如何分配处理值,但我想我可以推测一些细节。 博客文章描述了一个“三级方案”。 句柄被用作每个进程句柄表的索引,它包含指向每个进程句柄入口表的指针,该表又包含指向句柄的内核对象的指针。 Windows根据需要增长这些表,并且可能会在关闭后重新使用句柄来尝试节省内存。

Process Explorer中的句柄列表几乎没有差距,这也可能不是巧合。 由于进程打开和关闭处理所有的时间(通常由一些系统DLL在幕后完成),如果Windows没有积极地重复使用关闭的句柄,那么列表就会更加稀疏。 但Windows是否重用最低的句柄呢?

测试显示它没有。 我写了一个程序,创建三个句柄,依次关闭第一个,第三个和第二个,并在循环中重复所有这些。 如果Windows遵循POSIX规则,那么每个循环迭代将以相同的顺序创建相同的句柄值,从最小到最大。 但是,发生了什么事情呢,它是以相反的顺序创建了相同的句柄值,以致于它们被关闭了。 这表明Windows可能会以最近最近关闭的顺序重新使用句柄。 我的猜测是它通过在句柄表中保留未分配句柄的链表来实现这一点。

那么为什么你的套接字值从192开始? 可能是因为你的过程在那个时候已经有了47个打开的句柄。 为什么你的套接字相差20? 可能是因为你在创建每个套接字之间创建了4个其他的句柄。 Winsock本身可能会在每次创建套接字时在后台创建多个句柄。

更多的信息,你可以想要关于Winsock:(这意味着你应该阅读和吸收所有的;-)

http://www.tenouk.com/Winsock/Winsock2story.html

Jeremy是正确的,ID可以是文件HANDLE,窗口HANDLE,或者只是一个未使用的int值。 我已经看到了在IO完成端口时出现了什么样的指针,所以它可能会根据您使用的Windows网络的哪一部分而有所不同。 (Winsock,Winsock2等)