Winsock2套接字用ctypes调用CloseHandle报ERROR_INVALID_HANDLE,如何正确关闭?
解决Winsock2套接字关闭错误及句柄耗尽崩溃问题
这问题我之前碰到过好几个类似的,核心踩坑点就是你用错了关闭函数!Winsock的套接字句柄不能用CloseHandle()关闭,必须用Winsock专属的closesocket(),这也是你调用64次socket()后崩溃的根本原因。
为什么CloseHandle会返回ERROR_INVALID_HANDLE?
Windows里的HANDLE和Winsock的SOCKET虽然看起来都是数值,但属于完全不同的句柄空间:
CloseHandle()是用来关闭内核对象(比如文件、进程、线程)的系统调用;- 而
SOCKET是Winsock库自己维护的句柄,它的资源管理由Winsock负责,内核根本不认识这个句柄,所以调用CloseHandle()必然返回ERROR_INVALID_HANDLE。
更严重的是,误用CloseHandle不会释放Winsock内部的套接字资源,每创建一个套接字又不正确关闭,就会消耗Winsock的句柄池,当达到默认限制(通常是64个)时,后续的socket()调用就会失败,甚至直接导致程序崩溃。
正确的关闭步骤
按照你的代码结构,修正方式如下:
- 先正确加载并设置
closesocket函数的类型:# 从Winsock2库加载closesocket closesocket = ws2.closesocket closesocket.argtypes = [SOCKET] closesocket.restype = c_int - 当需要关闭套接字时,调用
closesocket而不是CloseHandle:# 关闭套接字 result = closesocket(self._clnt_socket) if result == SOCKET_ERROR: # 可在这里处理错误,比如调用WSAGetLastError()获取详细信息 pass - 最后,在程序退出前记得调用
WSACleanup(),释放Winsock的全局初始化资源:ws2.WSACleanup()
额外注意事项
- 确保每一个通过
socket()创建的套接字,都有对应的closesocket()调用——哪怕是连接失败的情况也要处理,避免句柄泄漏; - 把之前所有
CloseHandle的错误调用全部替换成closesocket后,句柄耗尽导致的崩溃问题应该就能解决。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

