gpt4 book ai didi

go - 如何高效实现json tcp server并防止socket flood?

转载 作者:IT王子 更新时间:2023-10-29 01:42:42 27 4
gpt4 key购买 nike

我正在寻找最有效的解决方案,有很多方法可以从套接字读取数据和解码 json。我显然应该使用 json.Encoder 和 json.Decoder,因为它们适合套接字的流式处理,但我有防止套接字泛滥的特定规则,如果单个消息大于 5 Kb,我必须关闭连接。我的消息结构是 JSON RPC。

在下面的示例中,我可以检查长度并应用策略:

connbuf := bufio.NewReader(conn)
msg, err := connbuf.ReadBytes('\n')
if len(msg) > 5 * 1024 {
conn.Close()
}
...
var req JSONRequest
err = json.Unmarshal(message, &req)
...

但是如果客户端推送数兆字节的数据而没有定界符,这些数据将在应用程序中,在服务器断开客户端连接之前已经在 msg 变量中。非常脆弱。

第二个例子使用解码器,根本没有机会检查大小。

dec = json.NewDecoder(conn)
for {
var req JSONRequest
if err := dec.Decode(&req); err == io.EOF {
break
} else if err != nil {
log.Println(err.Error())
return err
}
...
}

您能向我建议的最佳方法是什么?谢谢。

最佳答案

对于第一个示例,您可以使用 ReadLine :

connbuff := bufio.NewReaderSize(conn, 5*1024)
msg, isPrefix, err := connbuff.ReadLine()
if isPrefix {
// too long
}
...

如果 isPrefix 为真,则该行太长。如果您使用 bufio.Scanner,它实际上已经具有 64kb 的最大 token 大小。

正如 Tim Cooper 和 Dave C 所说,对于第二种情况,您可以使用 io.LimitedReader,但是 json 解码器有一个陷阱。它使用缓冲 IO,因此它会读取第一个请求。

要解决这个问题,请结合使用 io.MultiReaderio.LimitReader:

// to start with we have nothing buffered (an empty byte slice)
var buffered io.Reader = bytes.NewReader([]byte{})
for {
// combine whatever was in buffered with conn, but only up to 5kb
dec := json.NewDecoder(io.LimitReader(io.MultiReader(buffered, conn), 5*1024))
var req string
err := dec.Decode(&req)
if err == io.EOF {
break
} else if err != nil {
log.Fatalln(err)
}
// we probably read past the message, so save that to buffered
buffered = dec.Buffered()
}

关于go - 如何高效实现json tcp server并防止socket flood?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30220247/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com