You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用TCP协议绑定原始套接字到地址导致进程崩溃

问题成因分析

在Windows系统上,直接创建并绑定TCP协议的原始套接字会触发错误An invalid argument was supplied. (os error 10022),核心原因是Windows对原始套接字的功能做了严格的系统级限制:

  • TCP协议的原始套接字功能受限:Windows内核完全接管TCP协议的核心逻辑(如握手流程、序列号维护、流量控制等),不允许用户态程序通过SOCK_RAW类型的套接字直接操作TCP报文。当你创建Type::RAW+Protocol::TCP的套接字时,这类套接字仅能用于被动接收TCP数据包,无法执行绑定(bind)或主动发送数据的操作,强行调用就会返回无效参数错误。
  • 绑定操作不符合Windows套接字规则:对于TCP协议,常规场景使用的是SOCK_STREAM类型套接字;而SOCK_RAW类型套接字在Windows上仅支持ICMP、UDP等少数协议的主动操作,TCP不在此允许范围内,绑定操作本身对于TCP原始套接字就是非法参数。
  • 安全机制限制:即使以管理员权限运行程序,Windows也禁止用户态程序通过原始套接字发送TCP报文——这是为了防止绕过TCP栈的安全校验,避免恶意构造报文破坏网络秩序。

问题复现代码

use socket2::{Domain, Protocol, SockAddr, Socket, Type};
use std::{env, net::SocketAddr, process::{Command, Stdio}, thread, time::Duration, io::{BufReader, BufRead}};

fn main() -> std::io::Result<()> {
    let mut args: Vec<String> = std::env::args().collect();
    args.remove(0);

    if args.len() == 0 {
        let file_path = env::current_exe().unwrap();

        let file_path = file_path.to_str().unwrap();

        let (command, cmd_args) = (
            "powershell.exe",
            vec![
                String::from("-NoProfile"),
                String::from("-NoExit"),
                String::from("-Command"),
                String::from("Start-Process"),
                String::from(file_path),
                String::from("-Verb"),
                String::from("RunAs"),
                String::from("-ArgumentList"),
                String::from("'bind'"),
            ],
        );

        let mut cmd = Command::new(command)
            .args(cmd_args)
            .stderr(Stdio::piped())
            .spawn()
            .unwrap();

        let err = cmd.stderr.take().unwrap();
        let reader = BufReader::new(err);

        for line in reader.lines() {
            println!("{}", line.unwrap());
        }

        println!("DONE");
    } else {
        thread::sleep(Duration::from_secs(5));

        let address = SockAddr::from(SocketAddr::new([0, 0, 0, 0].into(), 0));

        let send_socket = Socket::new(Domain::IPV4, Type::RAW, Some(Protocol::TCP))?;

        send_socket.bind(&address)?;

        loop {}
    }

    Ok(())
}

内容的提问来源于stack exchange,提问作者NaN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 00:13:14