Windows下Socket错误码sckOpCanceled 1004的成因及编程复现方法
如何复现Socket错误码“The operation was canceled”
该错误对应Windows系统的ERROR_OPERATION_ABORTED(错误码995),核心是本地系统主动终止了Socket的IO操作,并非远程端发送特定“Cancel”信号。以下是几种不同语言的复现方式:
1. C++ (WinSock)
通过Windows API显式取消异步Socket操作:
#include <winsock2.h> #include <windows.h> #include <iostream> #pragma comment(lib, "ws2_32.lib") int main() { WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); // 创建TCP Socket SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); sockaddr_in serverAddr{}; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(8080); inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr); // 开启异步连接通知 WSAAsyncSelect(sock, GetConsoleWindow(), WM_USER + 1, FD_CONNECT); connect(sock, (sockaddr*)&serverAddr, sizeof(serverAddr)); // 立即取消Socket上的所有异步操作 CancelIoEx((HANDLE)sock, nullptr); // 捕获错误 MSG msg; while (GetMessage(&msg, nullptr, 0, 0)) { if (msg.message == WM_USER + 1) { int err = WSAGETSELECTERROR(msg.lParam); if (err == WSA_OPERATION_ABORTED) { std::cout << "复现成功:The operation was canceled" << std::endl; } break; } } closesocket(sock); WSACleanup(); return 0; }
原理:调用CancelIoEx主动终止挂起的异步连接操作,触发WSA_OPERATION_ABORTED错误。
2. Python (Windows平台)
借助Windows API取消Socket的IO操作:
import socket import win32file import win32api # 创建非阻塞Socket并发起连接 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setblocking(False) try: s.connect(("127.0.0.1", 8080)) except BlockingIOError: pass # 获取Socket句柄并取消IO操作 handle = win32file._get_osfhandle(s.fileno()) win32api.CancelIoEx(handle, None) # 触发错误 try: s.recv(1024) except OSError as e: if e.winerror == 995: print("复现成功:The operation was canceled") finally: s.close()
原理:取消挂起的连接操作后,执行读操作会抛出错误码995的异常,对应目标错误描述。
3. VB6 (贴合旧项目环境)
直接在VB6中调用Windows API取消Winsock操作:
Private Declare Function CancelIoEx Lib "kernel32.dll" (ByVal hFile As Long, ByVal lpOverlapped As Long) As Long Private Declare Function _get_osfhandle Lib "msvcrt.dll" (ByVal fd As Long) As Long Private sock As Winsock Private Sub Form_Load() sock.RemoteHost = "127.0.0.1" sock.RemotePort = 8080 sock.Connect ' 获取Socket句柄并取消操作 Dim handle As Long handle = _get_osfhandle(sock.SocketHandle) CancelIoEx handle, 0 End Sub Private Sub sock_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean) If Number = 10004 Then ' VB6中WSA_OPERATION_ABORTED对应错误码10004 MsgBox "复现成功:" & Description ' Description即为"The operation was canceled" End If End Sub
原理:取消Winsock控件的异步连接操作,触发Error事件并输出目标错误描述。
注意事项
- 所有示例需确保目标端口(如8080)未被监听,让Socket操作处于挂起状态,才能触发取消错误。
- 该错误的常见触发场景包括:线程终止、显式调用取消IO的API、进程退出前清理挂起操作等。
内容的提问来源于stack exchange,提问作者Kumaru
相关产品推荐
相关产品推荐

