为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
收到一只叮咚 2021-10-04 17:36:24
我正在寻找最有效的解决方案,有很多方法可以从套接字读取数据并解码 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 JSONRequesterr = 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   }   ...}您可以向我建议的最佳方法是什么?谢谢。
查看完整描述

1 回答

?
红糖糍粑

TA贡献1815条经验 获得超6个赞

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


connbuff := bufio.NewReaderSize(conn, 5*1024)

msg, isPrefix, err := connbuff.ReadLine()

if isPrefix {

  // too long

}

...

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


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


为了解决这个问题使用的组合io.MultiReader和io.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()

}


查看完整回答
反对 回复 2021-10-04
  • 1 回答
  • 0 关注
  • 218 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信