文本协议与二进制协议

  • 二进制协议就是一串字节流,通常包含消息头(header)和消息体(body)。消息头的长度固定,并且消息头包括了消息体的长度,这样就能从数据流中解析出一个完整的二进制数据。二进制协议的传输不需要通过添加冗余数据来分隔命令,因此传输效率较高。像 Smb、Http/2 协议都是二进制协议,二进制协议的一个特点是可以充分利用网络的全双工特点,提高网络传输的效率。
  • 文本协议一般由一串 ASCII 字符组成,这些字符包括数字,大小写字母、百分号,还有回车(\r),换行(\n)以及空格等等。像 Http、Redis 等协议均属于文本协议。一般文本协议主要是一问一答式的传输,这样就无法充分利用网络的全双工优势。
  • 市面上的 Http 代理服务器比较成熟并且稳定,比如 Nginx、apache 等,而随着 Http/2 的普及,Nginx 上也加入了 Http/2 的代理功能支持,这样也就实现了二进制协议的代理。这次我们主要讨论如何利用 golang 来设计并实现一个支持 TCP 透明代理并在此基础上加入对 Smb 协议的支持。

TCP 透明代理的设计

  • 作为透明代理方,需要处理的过程包括 Receive RequestSend RequestReceive ResponseSend Response 这四个过程。这四个过程均由独立的线程并行执行,并且需要给每个独立过程设置一定数量的缓冲区。
  • 透明代理既要处理与客户端的连接,也要处理与服务端的连接,并且要保证当某一端的连接关闭的时候,需要处理与另一端的连接,并平滑的退出上述的每个独立过程。
  • 其中设计的原则包括:谁写缓冲区负责关闭缓冲区,如果由读的一方关闭缓冲区,那么写的时候就会有问题;所有的连接处理都由 Proxy 来处理,不需要由四个独立线程来处理。

特殊协议的扩展

  • 目前的设计只是用来处理透明的 TCP 代理,如果需要针对特殊协议做修改等操作,则需要在 Proxy 阶段解析协议、修改协议然后重新组装协议后发送给对端。