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

Python跨路由器TCP套接字连接失败,报WinError 10060错误

问题

同一网络下用Python搭建的TCP套接字运行正常,但跨网络时无法连接。已将服务器绑定IP设为0.0.0.0,但客户端连接时出现socket错误10060。推测问题出在端口转发,但不知道如何配置。同时不清楚如何用Python获取设备公网IP(gethostbyname()仅返回私网IP),寻求帮助。

测试代码

Server.py

import socket
import struct

def send_msg(sock, msg):
    msg = struct.pack('>Q', len(msg)) + msg
    sock.sendall(msg)

def recv_msg(sock):
    raw_msglen = recvall(sock, 8)
    if not raw_msglen:
        return None
    msglen = struct.unpack('>Q', raw_msglen)[0]
    return recvall(sock, msglen)

def recvall(sock: socket.socket, n):
    data = bytearray()
    while len(data) < n:
        packet = sock.recv(n - len(data))
        if not packet:
            return None
        data.extend(packet)
    return data

HOST = '0.0.0.0'
PORT = 5000

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        while True:
            text = input("Enter text: ").encode("utf-8")
            send_msg(conn,text)
            echo = recv_msg(conn).decode("utf-8")
            print(echo)

(注:原代码缺少import socket和import struct,已补充)

Client.py

import socket
import struct

def send_msg(sock, msg):
    msg = struct.pack('>Q', len(msg)) + msg
    sock.sendall(msg)

def recv_msg(sock):
    raw_msglen = recvall(sock, 8)
    if not raw_msglen:
        return None
    msglen = struct.unpack('>Q', raw_msglen)[0]
    return recvall(sock, msglen)

def recvall(sock: socket.socket, n):
    data = bytearray()
    while len(data) < n:
        packet = sock.recv(n - len(data))
        if not packet:
            return None
        data.extend(packet)
    return data

#HOST = '192.168.0.220'
HOST = 'x.x.x.x' # 服务器公网IP
PORT = 5000

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    while True:
        data = recv_msg(s)
        send_msg(s,data)
解决方案

1. 配置端口转发

跨网络访问需在服务器所在路由器上配置端口转发,步骤如下:

  • 登录路由器管理后台(通常在浏览器输入192.168.1.1或192.168.0.1,具体参考路由器说明书)
  • 找到端口转发或虚拟服务器选项
  • 添加转发规则:
    • 外部端口:填写服务器监听的端口(如5000)
    • 内部端口:与外部端口保持一致(5000)
    • 内部IP地址:服务器设备的内网IP(可通过ipconfig(Windows)或ifconfig(Linux/macOS)查看)
    • 协议:选择TCP
  • 保存规则后重启路由器生效

2. 获取公网IP的Python方法

gethostbyname()仅能获取内网IP,要获取公网IP需访问外部服务,示例代码如下:

import requests

def get_public_ip():
    try:
        response = requests.get('http://httpbin.org/ip')
        return response.json()['origin']
    except Exception as e:
        print(f"获取公网IP失败: {e}")
        return None

if __name__ == "__main__":
    public_ip = get_public_ip()
    if public_ip:
        print(f"公网IP: {public_ip}")

(注:需先安装requests库,执行pip install requests)

3. 额外注意事项

  • 确保服务器设备防火墙开放监听端口(5000):Windows可在防火墙高级设置中添加入站规则;Linux执行ufw allow 5000/tcp
  • 部分运营商会使用CGNAT(运营商级NAT),此时设备无独立公网IP,端口转发无效,需使用内网穿透工具(如frp、ngrok)
  • 客户端连接时,HOST必须填写服务器的公网IP,而非内网IP

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 05:18:25