使用Golang的gorilla / websocket软件包的Websocket连接断开

I'm attempting to port a NodeJS script that establishes and maintains a Websocket connection to a third-party server to Go using the gorilla/websocket package. In the Node script, a pong is received following a ping, and the connection is kept alive indefinitely. In the Go script, ping/pong works but the connection is dropped by the server after about 30 seconds.

I suspect that the pings that are sent using the Go websocket package are malformed, but I can't pinpoint the cause of this. Comparing the captured, encrypted network traffic while running these programs shows no difference in the response length of the TCP requests and responses, so this may not be the issue. Any help would be greatly appreciated!

websocket.js

#!/usr/bin/env node

// npm install websocket@1.0.25 --save
const WebSocketClient = require('websocket').client;
const client = new WebSocketClient();

let lastPing = new Date().getTime();

client.on('connectFailed', function(error) {
    console.log('Connect Error: ' + error.toString());
});

client.on('connect', function(connection) {
    console.log('Connected to Server...');
    connection.on('error', function(error) {
        console.log("Connection Error: " + error.toString());
    });
    connection.on('close', function() {
        console.log('Connection Closed');
    });
    connection.on('message', function(message) {
      if (message.type === 'utf8') {
        console.log(message.utf8Data);
      }
    });
    connection.on('pong', function(){
      console.log('[pingpong] response took', (new Date().getTime() - lastPing) + 'ms');
    })

    function send(message) {
      if (connection.connected) {
          connection.sendUTF(message);
      }
    }

    // Send a ping every 10s
    // to keep the connection live
    setInterval(function(){
      lastPing = new Date().getTime();
      connection.ping();
    }, 10000);
});

client.connect('wss://ws.radarrelay.com/0x/v0/ws');

websocket.go

package main

import (
    "flag"
    "log"
    "os"
    "os/signal"
    "time"

    "github.com/gorilla/websocket"
)

var addr = "wss://api.radarrelay.com/0x/v0/ws"

func main() {
    flag.Parse()
    log.SetFlags(0)

    timeoutDuration := 2 * time.Minute

    interrupt := make(chan os.Signal, 1)
    signal.Notify(interrupt, os.Interrupt)

    c, _, err := websocket.DefaultDialer.Dial(addr, nil)
    if err != nil {
        log.Fatal("dial:", err)
    } else {
        log.Println("Connected to server")
    }

    c.SetPongHandler(func(str string) error {
        log.Println("pong received", str)
        return nil
    })

    defer c.Close()

    done := make(chan struct{})

    go func() {
        defer c.Close()
        defer close(done)
        for {
            c.SetReadDeadline(time.Now().Add(timeoutDuration))
            _, message, err := c.ReadMessage()
            if err != nil {
                log.Println("read:", err)
                return
            }
            if len(message) >= 2 {
                message = message[2:]
            }
            log.Printf("recv: %s", message)
        }
    }()

    ticker := time.NewTicker(10 * time.Second)
    defer ticker.Stop()

    for {
        select {
        case _ = <-ticker.C:
            err := c.WriteMessage(websocket.PingMessage, []byte{})
            if err != nil {
                log.Println("write:", err)
                return
            } else {
                log.Println("ping sent")
            }
        case <-interrupt:
            log.Println("interrupt")
            // To cleanly close a connection, a client should send a close
            // frame and wait for the server to close the connection.
            err := c.WriteMessage(
                websocket.CloseMessage,
                websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
            if err != nil {
                log.Println("write close:", err)
                return
            }
            select {
            case <-done:
            case <-time.After(time.Second):
            }
            c.Close()
            return
        }
    }
}
douzi115522
douzi115522 凉!乐意效劳。让第二只眼睛看起来有些东西总是很好。一直有人对我发呆。初步估算,SO就是大规模的服务。:)干杯。
2 年多之前 回复
douping1581
douping1581 好吧,这很尴尬-这就是问题所在。接得好。如果您在下面创建答案,我可以接受。
2 年多之前 回复
dpv46227
dpv46227 addr在节点的wss://ws.radarrelay.com/0x/v0/ws和go版本的wss://api.radarrelay.com/0x/v0/ws之间是不同的。那些决心使用不同IP的人,他们是否具有不同的入口基础架构?
2 年多之前 回复
duanfei8149
duanfei8149 根据对代码的快速检查,看起来两个程序包都为ping发送相同的数据:0x89、0x80和一个四字节掩码。
2 年多之前 回复
dougou7782
dougou7782 要记录未加密的数据,请将fmt.Println(“frame:%x%x ”,buf0,buf1)添加到Go代码和console.log(output);中。JS代码。
2 年多之前 回复
dos8410
dos8410 是的,但是从此特定第三方服务器的角度来看,格式不正确。上面的Golang脚本为我可以抛出的任何其他websocket服务器(包括我自己启动的服务器)建立了连接。我想比较每个脚本发送的ping帧的未加密内容,但是我不知道该怎么做。
2 年多之前 回复
dsbifvcxr458755493
dsbifvcxr458755493 因为您报告客户收到乒乓球,所以ping似乎必须格式正确。
2 年多之前 回复
dongming6201
dongming6201 将该代码粘贴到此处。站点规则规定必须在问题中包括代码,而不仅仅是链接到该代码。
2 年多之前 回复
douju2474
douju2474 始终在您的帖子中包含代码,以使代码示例最少(请参见“如何提问”)。
2 年多之前 回复
draj840143
draj840143 请参阅链接的要点。
2 年多之前 回复
dongsunny1113
dongsunny1113 让我们看一些代码。
2 年多之前 回复

1个回答



两者之间的地址不同。 节点代码正在与</ p>

  wss://ws.radarrelay.com/0x/v0/ws 
</ code> </ pre>

< p> go代码正在与之对话:</ p>

  wss://api.radarrelay.com/0x/v0/ws 
</ code> </ pre> \ n

看起来像那些解析为不同IP的地址,因此它们可能具有不同的入口基础结构,并且api子域上存在超时,而ws子域上不存在超时。 </ p>
</ div>

展开原文

原文

The addr is different between the two. The node code is talking to

wss://ws.radarrelay.com/0x/v0/ws

And the go code is talking to:

wss://api.radarrelay.com/0x/v0/ws

Looks like those resolve to different IPs, so perhaps they have different ingress infrastructure, and there is a timeout on the api subdomain that doesn't exist on the ws subdomain.

duandang2838
duandang2838 如果这是真正的问题,那就很好了:-)
2 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐