Go – TCP客户端经常错过次要的JSON回复

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

Go - TCP Client Often Misses Secondary JSON Reply

问题

我正在尝试编写一个TCP客户端,向本地托管的TCP服务器发送一个JSON RPC。服务器应立即返回两个回复。
TCP服务器托管在端口60000上。

以下是客户端代码的样子:

package main

import (
    "fmt"
    "log"
    "bufio"
    "net"
)

func main() {
    d := net.Dialer{ }
    c, err := d.Dial("tcp", "127.0.0.1:60000")

    if err != nil {
        log.Println(err)
        return
    }

    data := `{"id": 1,"method":"mining.configure","params": [["version-rolling"],{"version-rolling.mask": "1fffe000","version-rolling.min-bit-count": 16}]}`

    fmt.Fprintf(c, data+"\n")

    for {
        message, _ := bufio.NewReader(c).ReadString('\n')
        fmt.Println(message)
    }   
}

这是我发送的内容("data"变量)

{
 "id": 1,
 "method":"mining.configure",
 "params": [["version-rolling"],
           {"version-rolling.mask": "1fffe000",
            "version-rolling.min-bit-count": 16}]
}

这是预期的回复:

{"error":null,"id":1,"result":{"version-rolling":true,"version-rolling.mask":"1fffe000"}}
{"id":null,"method":"mining.set_version_mask","params":["1fffe000"]}

大多数情况下,我只收到第一个回复(带有"result"字段),而没有带有"method"字段的第二个JSON。有时我会同时收到两个回复。

但通常的回复是:

{"error":null,"id":1,"result":{"version-rolling":true,"version-rolling.mask":"1fffe000"}}

我知道当代码变得不确定时,这是由于异步问题引起的。
但是,我遇到的每个初学者教程都教授了这个编写TCP客户端的确切结构。它缺少了什么?
我已经使用Python和Twisted框架对服务器进行了大量的相同RPC调用测试,我100%的时间都能得到两个回复。这使我确信问题出在我的客户端代码中,而不是服务器上。

英文:

I'm trying to write a TCP client that sends out a JSON RPC to a locally hosted TCP server. The server should immediately return two replies.
The TCP server is hosted on port 60000.

This is what the client code looks like:

package main

import (
    "fmt"
    "log"
    "bufio"
    "net"
)

func main() {
    d := net.Dialer{ }
    c, err := d.Dial("tcp", "127.0.0.1:60000")

    if err != nil {
        log.Println(err)
        return
    }

    data := `{"id": 1,"method":"mining.configure","params": [["version-rolling"],{"version-rolling.mask": "1fffe000","version-rolling.min-bit-count": 16}]}`

    fmt.Fprintf(c, data+"\n")

    for {
        message, _ := bufio.NewReader(c).ReadString('\n')
        fmt.Println(message)
    }   
}

This is what I'm sending out ( the "data" variable )

{
 "id": 1,
 "method":"mining.configure",
 "params": [["version-rolling"],
           {"version-rolling.mask": "1fffe000",
            "version-rolling.min-bit-count": 16}]
}

This is the expected reply:

{"error":null,"id":1,"result":{"version-rolling":true,"version-rolling.mask":"1fffe000"}}
{"id":null,"method":"mining.set_version_mask","params":["1fffe000"]}

Most of the time I only get the first reponse (has the result "field") without the second JSON that has the "method" field. Sometimes I get both.

But this is the usual reply:

{"error":null,"id":1,"result":{"version-rolling":true,"version-rolling.mask":"1fffe000"}}

I know that when code becomes non-deterministic like this it's because of an asynchronous issue going on.
But every beginner tutorial I encountered teaches this exact structure for writing a TCP client. What's missing from it?
I've tested the same RPC call to the server extensively with Python with the Twisted framework and I get back the both replies 100% of the time. This makes me certain the issue is within my client code and not the server.

答案1

得分: 3

根据接收数据的时间,ReadString函数可能会缓冲超过\n的数据。问题中的代码在每次循环迭代时都会丢弃读取器和读取器中缓冲的数据。

为了避免丢弃数据,可以在循环内部创建读取器,并在循环中重复使用:

r := bufio.NewReader(c)
for {
    message, _ := r.ReadString('\n')
    fmt.Println(message)
}
英文:

Depending on the timing that data is received, the call to ReadString can buffer data past the \n. The code in the question discards the reader and data buffered in the reader on each iteration of the loop.

To avoid discarding data, create the reader once and reuse inside the loop:

r := bufio.NewReader(c)
for {
    message, _ := r.ReadString('\n')
    fmt.Println(message)
}   

huangapple
  • 本文由 发表于 2022年6月14日 00:47:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/72606369.html
匿名

发表评论

匿名网友

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

确定