Windows下Python 3使用Socket出现Winsock Error 10014问题求助
Hey there, let's break down what's causing that frustrating Winsock 10014 error and how to fix it. First, a quick primer: error 10014 maps to WSAEFAULT, which means the system detected an invalid pointer or address parameter—so Python's socket module is getting a handle it can't work with.
Why This Happens
On Windows, socket handles work differently than they do on Unix-like systems. When you pass a raw handle (from your C extension) to socket.socket(fileno=...), Python expects that handle to be a valid, process-owned socket handle that fits its internal management model. Common issues here include:
- Mismatched architecture: If your Python is 64-bit but your C extension is 32-bit (or vice versa), the handle gets truncated when passed as a long integer, turning it into an invalid value.
- Invalid/closed handle: The C extension might be returning a handle that's already closed, doesn't belong to the current process, or isn't actually a socket handle at all.
- Python's socket wrapper limitations: Python's socket class doesn't always play nice with raw Windows socket handles that weren't created by its own module—it might fail to properly associate the handle with its internal state.
Fixes to Try
1. Return a Python Socket Object from Your C Extension (Recommended)
Instead of passing a raw handle back to Python, wrap it directly in a Python socket object in your C code. This avoids all the cross-compatibility headaches. Here's a quick snippet of how to do this:
#include "Python.h" #include "socketmodule.h" static PyObject* get_connected_socket(PyObject* self, PyObject* args) { // Replace this with your code to retrieve the valid socket handle SOCKET target_sock = ...; if (target_sock == INVALID_SOCKET) { PyErr_SetString(PyExc_OSError, "Failed to retrieve valid socket handle"); return NULL; } // Use Python's built-in function to wrap the socket handle return PySocket_FromSocketDescriptor((int)target_sock); } // Module setup code omitted for brevity
With this change, your Python code simplifies to:
import socket, my_custom_socket_address_getting_module connectedSocket = my_custom_socket_address_getting_module.get() clientAddress = connectedSocket.getpeername()
PySocket_FromSocketDescriptor handles all the Windows-specific logic to make sure the socket is properly recognized by Python's socket module.
2. Validate Handle Compatibility
If you must pass the raw handle:
- Check architecture alignment: Ensure both your Python interpreter and C extension are built for the same bitness (32-bit or 64-bit). Mismatches will corrupt the handle value.
- Verify handle validity: In your C extension, add checks to confirm the handle is a valid, connected socket before returning it. Use Windows API calls like
getsockoptto test if the handle is alive. - Avoid closed handles: Make sure the socket isn't being closed elsewhere in your code before Python tries to use it.
3. Explicitly Set Socket Type When Creating the Python Object
If you know the type of socket (e.g., SOCK_STREAM for TCP), try specifying it when creating the Python socket object:
connectedSocket = socket.socket(fileno=underlyingSocketFileno, type=socket.SOCK_STREAM)
This gives Python more context about the socket, which might help it properly initialize the internal state.
Final Notes
The most reliable fix by far is wrapping the socket handle in a Python socket object directly in your C extension. It eliminates the guesswork of passing raw handles across language boundaries, especially on Windows where socket management is more strict.
内容的提问来源于stack exchange,提问作者benjamin.hammond

