你可以使用json.Decoder来解码单个JSON消息,并在之后切换连接到不同的协议。

huangapple go评论83阅读模式
英文:

How can I use json.Decoder to decode a single json message and switch the connection to a different protocol going foward?

问题

我正在开发一个基于TCP的代理,它必须在给定的连接上首先进行一个REQ/REPLY握手的JSON交互。由于JSON是一种自解释的协议,我使用Go的json.Decoder来完成这个工作,它能很好地完成这个任务。

以下是我采取的步骤:

  1. 拨号连接到远程服务器
  2. 向远程服务器写入一个JSON请求(REQ)
  3. 从同一远程服务器读取一个JSON回复(完成代理握手REPLY)
  4. 在有效的JSON握手之后,将客户端连接传递给代码的另一部分,从此刻开始将切换到基于文本的协议。

问题是,当json.Decoder将数据读入其内部缓冲区时,它可能会读取比所需更多的数据,此时json.Decoder有一个Buffered()方法,它返回一个带有剩余数据的io.Reader。

现在,这些数据(在Buffered()方法中可用)是需要在JSON握手完成后从连接中读取的基于文本的协议数据。但是,如果我不考虑剩余的缓冲区而直接传递连接,连接将进入锁定状态,因为它在等待永远不会到来的数据。处理基于文本的协议的代码在继续之前期望一个net.Conn,一旦我传递了连接(在JSON握手完成后),使用连接的代码就会理解如何在这一点上使用基于文本的协议。因此,工作应该有一个明确的边界。

我的问题是,如何解决这个问题的理想方式,以便我仍然可以利用json.Decoder,但确保当我将连接传递给代理代码的不同部分时,我知道基于文本的协议数据的起始位置仍然可读。我需要以某种方式将json.Decoder的剩余数据放回连接的前面,以便它可以在将来正确地读取。

非常感谢您的任何见解。

英文:

I am working on a TCP-based proxy that must first do a REQ/REPLY handshake in json on a given connection. Because JSON is a self-delimiting protocol I reach for Go's json.Decoder to pull off this work which does the job nicely.

Here are the steps I take:

  1. Dial a connection to a remote server
  2. Write a single json request to a remote server (REQ)
  3. Read a single json reply from the same remote server (completing the proxy handshake REPLY)
  4. Upon a valid json handshake, pass the client connection onto another part of the code which will (going forward) switch to a text based protocol from this point on.

The problem is, when json.Decoder reads data into its internal buffer it can potentially read more data than it needs in which case the json.Decoder has a Buffered() method which gives back an io.Reader with the remainder of the data.

This data (available in the Buffered() method) is now the text-based protocol data which needs to get read from the connection after the json hand-shake did its work. But if I pass the connection forward as is without considering the left over buffer, the connection gets into a locked state because it is waiting to read this data which never comes. The code that deals with the text-based protocol expects a net.Conn going forward and once I pass the connection forward (after the json handshake has been made) the code utilizing the connection understands how to speak the text-based protocol at this point on. So there should be a clear boundary of work.

My question is what is the ideal way to solve this issue so I can still take advantage of the json.Decoder, but ensure that when I pass the connection to a different part of the code in my proxy I know the start of the data for the text-based protocol will still be readable. I somehow need to take the remaining data in the json.Decoder's Buffered() method and put that back in front of the connection so it can be properly read going forward.

Any insight is much appreciated.

答案1

得分: 0

你可以尝试使用以下代码:

type ConnWithBuffIncluded struct{ // 实现 net.Conn 接口,以便可以通过管道传递
    net.Conn
    json.Decoder
}

func (x ConnWithBuffIncluded) Read(p []byte) (n int, err error){ // 从两个来源读取数据
    return io.MultiReader(x.Decoder.Buffered(), x.Conn).Read(p)
}

这段代码定义了一个名为ConnWithBuffIncluded的结构体,它包含了net.Connjson.Decoder两个字段。通过实现Read方法,该结构体可以从两个来源读取数据,即Decoder的缓冲区和Conn连接。

英文:

You can try

type ConnWithBuffIncluded struct{ //Implement net.Conn so can be passed through pipeline
    net.Conn
    json.Decoder
}

func (x ConnWithBuffIncluded) Read(p []byte) (n int, err error){ //Will Read both sources
    return io.MultiReader(x.Decoder.Buffered(), x.Conn).Read(p)
}

huangapple
  • 本文由 发表于 2015年1月12日 13:19:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/27895746.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定