首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Python 原始 Socket 網路監聽:WinError 10022 參數無效解析

     編輯:程式設計綜合問答

錯誤程式碼

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
while True:
    print(s.recvfrom(65565))  # OSError: [WinError 10022] 提供了一個無效的參數

錯誤分析

  1. 緩衝區大小超限:`recvfrom(bufsize)` 的 `bufsize` 參數在 Windows 上受限於底層協定堆疊實作,通常**最大 65535 位元組** (IPv4 封包理論上限)。傳入 `65565` 直接導致 `WSAEINVAL` (10022)。
  2. 原始 Socket 權限:Windows 要求**管理員權限**才能建立 `SOCK_RAW`,否則 `socket()` 即會失敗。
  3. IPPROTO_TCP 限制:Windows 對原始 TCP Socket 支援極差,通常只能接收 ICMP/IGMP 或透過 `SIO_RCVALL` 開啟混雜模式捕獲所有 IP 封包。

修正方案

1. 修正緩衝區大小

s.recvfrom(65535)  # 最大合法值

2. 以管理員身分執行

  • CMD/PowerShell 右鍵「以系統管理員身分執行」。
  • 或在程式碼中請求 UAC 提權 (需打包 exe)。

3. 正確開啟混雜模式捕獲封包 (Windows)

import socket
import struct

# 建立原始 Socket (捕獲所有 IP 封包)
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
s.bind(("0.0.0.0", 0))  # 綁定所有介面
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)  # 包含 IP 標頭

# 啟用混雜模式 (SIO_RCVALL)
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

try:
    while True:
        # 緩衝區 65535
        data, addr = s.recvfrom(65535)
        print(f"從 {addr} 收到 {len(data)} 位元組")
        # 這裡解析 IP/TCP/UDP 標頭...
except KeyboardInterrupt:
    pass
finally:
    # 關閉混雜模式
    s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
    s.close()

替代方案:使用成熟函式庫

  • Scapy:`sniff(prn=callback, filter="tcp")`,跨平台、功能強大、語法優雅。
  • pcapy / pylibpcap:libpcap 繫結,效能高,標準封包捕獲 API。
  • psutil:若僅需連線統計、流量統計,無需原始 Socket,`psutil.net_connections()`、`psutil.net_io_counters()` 即可。

結論

WinError 10022 核心原因是 **`recvfrom` 緩衝區參數超過 65535** 且 **缺乏管理員權限/混雜模式設定**。修正參數、提權、正確 `ioctl` 開啟混雜模式,或直接改用 **Scapy/psutil** 等高階函式庫,避免造輪子踩坑。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved