猿问

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

我正在寻找最有效的解决方案,有很多方法可以从套接字读取数据并解码 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

   }

   ...

}

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


收到一只叮咚
浏览 219回答 1
1回答

红糖糍粑

对于第一个示例,您可以使用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()}
随时随地看视频慕课网APP

相关分类

Go
我要回答