Golang在第一次读取后,通过websocket的bufio断开连接。

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

Golang bufio from websocket breaking after first read

问题

我正在尝试从一个websocket中流式传输JSON文本。然而,在初始读取之后,我注意到流似乎中断/断开连接。这是来自Pleroma服务器(类似于Mastodon)。我正在使用默认的Golang websocket库。

在初始的JSON文本响应之后,for循环中断了。我期望它每隔几秒钟发送一条新消息。

可能是什么原因导致这种情况?如果可以在使用bufio的情况下使用Gorilla websocket库,我愿意切换到它。

谢谢!

英文:

I am trying to stream JSON text from a websocket. However after an initial read I noticed that the stream seems to break/disconnect. This is from a Pleroma server (think: Mastodon). I am using the default Golang websocket library.

package main

import (
	"bufio"
	"fmt"
	"log"

	"golang.org/x/net/websocket"
)

func main() {
	origin := "https://poa.st/"
	url := "wss://poa.st/api/v1/streaming/?stream=public"

	ws, err := websocket.Dial(url, "", origin)
	if err != nil {
		log.Fatal(err)
	}

	s := bufio.NewScanner(ws)
	for s.Scan() {
		line := s.Text()
		fmt.Println(line)
	}
}

After the initial JSON text response, the for-loop breaks. I would expect it to send a new message every few seconds.

What might be causing this? I am willing to switch to the Gorilla websocket library if I can use it with bufio.

Thanks!

答案1

得分: 2

尽管x/net/websocket连接具有与io.Reader中的Read方法相同的签名,但连接不像io.Reader那样工作。当使用bufio.Scanner包装连接时,连接将无法按预期工作。

poa.st端点发送一系列消息,其中每个消息都是一个JSON文档。使用以下代码使用Gorilla包读取消息:

url := "wss://poa.st/api/v1/streaming/?stream=public"
ws, _, err := websocket.DefaultDialer.Dial(url, nil)
if err != nil {
    log.Fatal(err)
}
defer ws.Close()

for {
    _, p, err := ws.ReadMessage()
    if err != nil {
        log.Fatal(err)
    }
    // p是一个包含JSON文档的[]byte。
    fmt.Printf("%s\n", p)
}

Gorilla包中有一个用于解码JSON消息的辅助方法。以下是如何使用该方法的示例。

url := "wss://poa.st/api/v1/streaming/?stream=public"
ws, _, err := websocket.DefaultDialer.Dial(url, nil)
if err != nil {
    log.Fatal(err)
}
defer ws.Close()

for {
    // JSON文档是包含两个字段的对象,
    // 事件类型和有效载荷。有效载荷本身是一个JSON文档。
    var e struct {
        Event   string
        Payload string
    }

    err := ws.ReadJSON(&e)
    if err != nil {
        log.Fatal(err)
    }
    // TODO: 根据e.Event解码e.Payload
}
英文:

Although x/net/websocket connection has a Read method with the same signature as the Read method in io.Reader, the connection does not work like an io.Reader. The connection will not work as you expect when wrapped with a bufio.Scanner.

The poa.st endpoint sends a stream of messages where each message is a JSON document. Use the following code to read the messages using the Gorilla package:

url := "wss://poa.st/api/v1/streaming/?stream=public"
ws, _, err := websocket.DefaultDialer.Dial(url, nil)
if err != nil {
	log.Fatal(err)
}
defer ws.Close()

for {
	_, p, err := ws.ReadMessage()
	if err != nil {
		log.Fatal(err)
	}
    // p is a []byte containing the JSON document.
	fmt.Printf("%s\n", p)
}

The Gorilla package has a helper method for decoding JSON messages. Here's an example of how to use that method.

url := "wss://poa.st/api/v1/streaming/?stream=public"
ws, _, err := websocket.DefaultDialer.Dial(url, nil)
if err != nil {
	log.Fatal(err)
}
defer ws.Close()

for {
    // The JSON documents are objects containing two fields, 
    // the event type and the payload. The payload is a JSON
    // document itself.
    var e struct {
		Event   string
		Payload string
	}

	err := ws.ReadJSON(&e)
	if err != nil {
		log.Fatal(err)
	}
    // TODO: decode e.Payload based on e.Event
}

huangapple
  • 本文由 发表于 2022年2月9日 06:09:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/71041497.html
匿名

发表评论

匿名网友

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

确定