【发布时间】:2015-01-12 05:19:54
【问题描述】:
我正在开发一个基于 TCP 的代理,它必须首先在给定连接上以 json 格式进行 REQ/REPLY 握手。因为 JSON 是一个自定界协议,所以我使用 Go 的 json.Decoder 来完成这项工作,该工作做得很好。
这是我采取的步骤:
- 拨号连接到远程服务器
- 将单个 json 请求写入远程服务器 (REQ)
- 从同一远程服务器读取单个 json 回复(完成代理握手回复)
- 在有效的 json 握手后,将客户端连接传递到代码的另一部分,该部分将(继续)从此时开始切换到基于文本的协议。
问题是,当 json.Decoder 将数据读取到其内部缓冲区时,它可能可能读取比它需要的更多的数据,在这种情况下,json.Decoder has a Buffered() 方法返回一个带有其余数据。
这个数据(在 Buffered() 方法中可用)现在是基于文本的协议数据,需要在 json 握手完成后从连接中读取。但是,如果我在不考虑剩余缓冲区的情况下按原样传递连接,则连接将进入锁定状态,因为它正在等待读取这些永远不会到来的数据。处理基于文本的协议的代码 期望 一个 net.Conn 继续前进,一旦我将连接向前传递(在 json 握手之后),使用连接的代码就知道如何说在这一点上基于文本的协议。所以应该有明确的工作界限。
我的问题是解决此问题的理想方法是什么,因此我仍然可以利用 json.Decoder,但请确保当我将连接传递到代理中代码的不同部分时,我知道开始基于文本的协议的数据仍然是可读的。我不知何故需要在 json.Decoder 的 Buffered() 方法中获取剩余数据并将其放回连接前面,以便以后可以正确读取。
非常感谢任何见解。
【问题讨论】:
-
连接上运行的是什么协议?您应该在自己的消息中用不同的内容将每个数据包装箱,至少类似于 [size][payload]。
-
@fabrizioM - 基于文本的协议是专有的换行符分隔协议。我考虑过按照您的建议做,但它似乎没有必要,因为 json 是自定界的,并且基于文本的协议由换行符定界……如果不是 json.Decoder 缓冲区中的剩余数据,一切正常。跨度>
-
给定
io.Reader,您可以编写自己的结构来实现io.Reader,这需要两件事-[]bytes带有要提供的前缀和io.Reader,当前缀全部提供时使用。跨度> -
@TomaszKłak - 是的,我一直在考虑这些方面的一些事情......我忘记提及的另一个约束:处理文本协议的代码不需要 io.Reader 而是网络.Conn 我可能无法更改。
-
@ralph-caraveo
net.Conn也是一个Interface,所以同样的原则应该适用。