使用Python socket模块连接Socks4代理的实现方法与报错排查
问题修复方案
根本原因
你遇到的ConnectionResetError报错或recv卡住的核心问题是二进制报文构造时的字符编码错误:
你最初的代码将包含转义字节的字符串调用encode()方法编码,默认使用UTF-8编码规则,其中\xbc、\xb8这类超出ASCII范围的字节值会被转换为多字节的UTF-8序列,最终发送的报文和你预期的SOCKS4协议要求的单字节序列完全不符。代理服务器收到非法格式的报文后,要么直接主动断开连接,要么不返回任何响应,就会出现你遇到的两种异常表现。
验证过的正确写法
你排查出的直接构造bytearray的方案是完全正确的,该方式会严格按照你指定的十六进制值生成原始字节,不会经过字符编码转换,完全符合SOCKS4协议的报文格式要求。
修正后的完整代码示例:
import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('148.77.34.200',54321)) # 直接构造二进制报文,避免字符编码转换错误 req = bytearray([0x04,0x01,0x00,0x50,0xbc,0xb8,0x15,0x6c,0x43,0x68,0x61,0x64,0x00]) sock.send(req) print('Sent data') a = sock.recv(8) print(f'Received data {a}') sock.close()
拓展注意事项
- 开发二进制协议相关的网络代码时,永远优先直接使用
bytes/bytearray类型构造报文,不要通过字符串转编码的方式生成,避免字符编码逻辑污染原始二进制数据 - 如果需要动态修改报文中的端口、IP、用户名等字段,可以使用Python标准库的
struct模块打包报文,用对应的格式符自动处理大端字节序等协议要求,代码可维护性更高 - 收到代理的8字节响应后,需要先判断第二个字段的值是否为
0x5A,确认代理请求成功后再进行后续的流量转发操作
内容的提问来源于stack exchange,提问作者pennacap
相关产品推荐
相关产品推荐

