有问题的代码部分大致如下:
import socket, my_custom_socket_address_getting_module
underlyingSocketFileno = my_custom_socket_address_getting_module.get()
connectedSocket = socket.socket( fileno=underlyingSocketFileno )
clientAddress = connectedSocket.getpeername()
其中“my_custom_socket_address_getting_module”是一个自定义C扩展,它返回我机器上一个打开套接字的地址(作为一个长整数)。
前两行似乎运行良好,并且Python套接字对象看起来很合理(例如fd
和其他套接字属性在调试器中看起来正确),但尝试在对象上调用getpeername
抛出以下异常:
<class 'OSError'>:[WinError 10014] The system detected an invalid pointer address in attempting to use a pointer argument in a call
由于我让Python构建Python套接字(也可能是支持OS SOCKET
),我不知道破坏的指针地址将来自何处。
我相信从我的自定义模块提供给Python的套接字地址是正确的,并且它返回的套接字地址是有效的,因为扩展与我的旧Python版本完美配合。
当我转向更新版本的Python(3.6.5)时,这个问题就出现了 - 关于为什么这个新版本会这样做的任何想法? 以前的工作版本是Python 1.5.2(是的,真的)。
(操作系统是Microsoft Windows 8.1 64,Python 3.6.5,使用MSVCC v.1911构建)
答案 0 :(得分:4)
来自socket.socket
构造函数的Python 3 Docs:
如果指定了fileno,则忽略其他参数,从而导致返回具有指定文件描述符的套接字。
对于文档的作者来说,这可能是显而易见的,但看起来这只有在与您传入的fileno
相关联的套接字是由Python创建的情况下才有效。如果您尝试连接到由扩展模块打开的套接字,那么Python将使用您提供的socket
创建一个fileno
对象,但其他套接字属性(类型,系列,协议) )将被设置为默认值。
在这种情况下,套接字是IPv6套接字,但Python套接字的默认值是IPv4。手动指定套接字类型和系列解决了该问题。