先读满八个字节,再交出 SOCKS4 隧道
通过解析 SOCKS4 响应的固定边界,避免吞掉目标服务发来的问候,也避免等待根本不存在的字节。
SOCKS4 连接请求已经成功,应用却始终看不到服务器发来的问候。一个值得查看的地方是连接器的第一次读取。十六字节的读取对八字节的 SOCKS4 响应来说太大了。
| 响应字段 | 字节 |
|---|---|
| 响应版本字段 | 1 |
| 结果码 | 1 |
| 端口字段 | 2 |
| 地址字段 | 4 |
结果码 0x5a 表示请求已被批准。SOCKS4a 改变的是请求携带主机名的方式,并不会把响应变成十六字节。
响应之后,同一条 TCP 流继续承载目标协议。邮件服务器可能立刻发送问候,于是一次吃掉十六个可用字节的读取,可能把完整的代理响应连同该问候的前八个字节一起取走。如果后面还什么都没有,超大阻塞读取反而会多出一次不必要的等待。
精确长度是解析器的责任
请求一次八字节,并不足以证明真的到了八字节。流读取可能返回更少。 请在期限内准确收齐响应的长度,遇到已关闭或失败的流就停止,检查响应,并把后续字节留给应用。
如果连接器使用更大的缓冲读取,就要保留边界之后的所有内容并交给下游消费者。丢弃多余数据,只是换了个读取大小的同一种数据丢失。
SOCKS5 需要自己的解析器。它的响应地址长度会随地址类型变化。把每次代理读取都换成固定的八字节读取,只会修好一个协议,同时弄坏另一个。