SOCKS4 连接请求已经成功,应用却始终看不到服务器发来的问候。一个值得查看的地方是连接器的第一次读取。十六字节的读取对八字节的 SOCKS4 响应来说太大了。

响应字段字节
响应版本字段1
结果码1
端口字段2
地址字段4

结果码 0x5a 表示请求已被批准。SOCKS4a 改变的是请求携带主机名的方式,并不会把响应变成十六字节。

响应之后,同一条 TCP 流继续承载目标协议。邮件服务器可能立刻发送问候,于是一次吃掉十六个可用字节的读取,可能把完整的代理响应连同该问候的前八个字节一起取走。如果后面还什么都没有,超大阻塞读取反而会多出一次不必要的等待。

精确长度是解析器的责任

请求一次八字节,并不足以证明真的到了八字节。流读取可能返回更少。 请在期限内准确收齐响应的长度,遇到已关闭或失败的流就停止,检查响应,并把后续字节留给应用。

如果连接器使用更大的缓冲读取,就要保留边界之后的所有内容并交给下游消费者。丢弃多余数据,只是换了个读取大小的同一种数据丢失。

SOCKS5 需要自己的解析器。它的响应地址长度会随地址类型变化。把每次代理读取都换成固定的八字节读取,只会修好一个协议,同时弄坏另一个。

相关文章