Tag Archives:Win32
WinSock 可以把 SOCKET 类型转换成 int 保存么?
在 Linux/Unix 等 posix 环境中,每个套接字都是一个文件描述符fd,类型是int,使用起来非常方便;但在 Win32 环境中是SOCKET 类型被定义成UINT_PTR ,是一个指针,在 x64 环境中一个SOCKET 占用 8 个字节。
那么是否能将SOCKET 类型强制转换成int 类型保存没?这样就能统一用int 在所有平台下表示套接字了,同时在 x64 环境下这样将 64 位的指针转换为 32 位的整数是否安全?
答案是可以的,下面将从三个方面说明一下。
Kernel Object
每个 SOCKET 背后其实都是一个指向 Kernel Object 的 Handle,而每个进程的 Handle 的数量是有限的,见 MSDN 的Kernel Objects:
Kernel object handles are process specific. That is, a process must either create the object or open an existing object to obtain a kernel object handle. The per-process limit on kernel handles is 2^24. However, handles are stored in the paged pool, so the actual number of handles you can create is based on available memory.
单进程不会超过 2^24 个,每个 Kernel Object 需要通过一个 Handle 来访问:

这些 Handle 保存于每个进程内位于低端地址空间的 Handle Table 表格,而这个 Handle Table 是连续的,见 MSDN 中的Handles and objects:
Each handle has an entry in an internally maintained table. Those entries contain the addresses of the resources, and the means to identify the resource type.
这个 Handle Table 表格对用户进程只读,对内核是可读写,在进程结束时,操作系统会扫描整个表格,给每个有效 Handle 背后指向的 Kernel Object 解引用,来做资源回收。
所以看似是UINT_PTR 指针的SOCKET 类型,其实也只是一个表格索引而已,这个 Handle Table 表格的项目有数量限的(最多 2^24 个元素),内容又是连续的,那当然可以用int 来保存。
开源案例
故此不少开源项目也会选择在 Windows 环境下将SOCKET 类型直接用int 来存储,比如著名的 openssl 在include/internal/sockets.h 里有解释:
/* * Even though sizeof(SOCKET) is 8, it's safe to cast it to int, because * the value constitutes an index in per-process table of limited size * and not a real pointer. And we also depend on fact that all processors * Windows run on happen to be two's-complement, which allows to * interchange INVALID_SOCKET and -1. */# define socket(d,t,p) ((int)socket(d,t,p))# define accept(s,f,l) ((int)accept(s,f,l))所以 openssl 不论什么平台,都将套接字看作int 来使用:
int SSL_set_fd(SSL *ssl, int fd);int SSL_set_rfd(SSL *ssl, int fd);int SSL_set_wfd(SSL *ssl, int fd);所以它的这些 API 设计,清一色的int 类型。
程序验证
道理前面都讲完了,下面写个程序验证一下:

在现MSN魔法表情
下面是播放时候的效果图:

MSN 的魔法表情实在是 COOL,兴趣之下自己也做了一个特效演示将 FLASH 拖到窗口上面,然后点“特效”, 如果桌面是 32 位的效果非常漂亮,可以拖动图形,现在就下载:
最好笑的事情是那天发现有些聊天软件的魔法表情居然是假的,它是把桌面抓下来然后用 IE 控件来播放 Flash, 顺便把抓下来的桌面当背景。或者直接用 ColorKey -_-

