dsajdgjadwqe3247382 2019-08-03 18:07
浏览 1375

如何隔离闭合1006(异常闭合):意外的EOF

I've been trying to subscribe to this API feed: https://www.cryptofacilities.com/resources/hc/en-us/articles/360000578294-Fills

Whenever I try to subscribe, it looks like I'm able to send the payload with WRITEJSON, but what I receive from my Read method is

websocket: close 1006 (abnormal closure): unexpected EOF.

The full terminal message is:

2019/08/04 22:20:31 recv: {"event":"info","version":1} 2019/08/04 22:20:31 recv: {"event":"subscribed","feed":"heartbeat"} 2019/08/04 22:20:31 recv: {"event":"challenge","message":"c6e55c07-d07a-4560-9283-be75ee458433"} ^C2019/08/04 22:21:50 interrupt 2019/08/04 22:21:50 write close: write tcp 192.168.1.6:49624->104.16.51.17:443: write: broken pipe

I understand from here that the status code means that my client closed the connection. I'm unable to track down this problem.

I've tried running race detection, turning off firewall (I have a Mac, and tried to turn off the antivirus - found out it's built in. Would this be worth pursuing?) increasing the handshake timeout, handling the error with a close frame, a different OS, increasing the buffer size, and max message size. A lot of it in reference to this post:

https://github.com/gorilla/websocket/issues/321

This is my client:

package websocket

import (
    "crypto/hmac"
    "crypto/sha256"
    "crypto/sha512"
    "encoding/base64"
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "time"

    "github.com/gorilla/websocket"
)

var addr = "wss://www.cryptofacilities.com/ws/v1"

var Wait = 50000 * time.Second

var MaxMessageSize int64 = 100000

//WebSocket connection struct to pass into other methods
type WebSocket struct {
    Conn *websocket.Conn
}

//Message represents the public server push messages
type Message struct {
    Event   string
    Feed    string
    Message interface{}
}

type ChallengeSub struct {
    Event   string `json:"event"`
    Message string `json:"message"`
}

type HeartBeat struct {
    Event   string
    Message string
}

type FillSubscribe struct {
    Event             string `json:"event"`
    Feed              string `json:"feed"`
    APIKey            string `json:"api_key"`
    OriginalChallenge string `json:"original_challenge"`
    SignedChallenge   string `json:"signed_challenge"`
}

//OpenWebSocket Connects to kraken API and returns a connection
func OpenWebSocket() (*WebSocket, error) {
    conn, response, err := websocket.DefaultDialer.Dial(addr, nil)
    if err != nil {
        return nil, err
    }
    if response.StatusCode != http.StatusSwitchingProtocols {
        return nil, fmt.Errorf("failed to upgrade protocol to websocket")
    }
    return &WebSocket{Conn: conn}, nil
}

//HeartBeat subscribes to the pingpong feed to keep the connection alive
func (c *WebSocket) HeartBeat() error {

    ping := map[string]interface{}{
        "event": "subscribe",
        "feed":  "heartbeat",
    }
    c.Conn.SetWriteDeadline(time.Now().Add(Wait))
    err := c.Conn.WriteJSON(ping)

    return err
}

func (c *WebSocket) Next() ([]byte, error) {
    _, payload, err := c.Conn.ReadMessage()
    return payload, err
}

//Challenge requests the UUID from kraken API for auth handshake
func (c *WebSocket) Challenge() error {

    challengeRequest := map[string]interface{}{
        "event":   "challenge",
        "api_key": "rhsqfT66dxTF7g2O7/t5Cluubjw4MlEz1UoBrZBjf8JocQ/q49j9rH9m",
    }
    c.Conn.SetWriteDeadline(time.Now().Add(Wait))
    err := c.Conn.WriteJSON(challengeRequest)
    if err != nil {
        log.Println("write:", err)

        return err
    }

    return err
}

func (c *WebSocket) Decode(payload []byte) (string, string) { //Decode takes in a connection and reference to Message struct
    var msg json.RawMessage
    env := Message{
        Message: &msg,
    }
    if err := json.Unmarshal([]byte(payload), &env); err != nil {
        log.Fatal(err)
    }
    switch env.Event {

    case "challenge":
        var s ChallengeSub
        if err := json.Unmarshal(msg, &s.Message); err != nil {
            log.Fatal(err)
        }
        message, signed := c.Signature(s.Message)
        c.FillSubscribe(message, signed)

        return message, signed

    case "info":
        {
            fmt.Println("Connected:", env.Event)
        }
    case "subscribed":
        {
            fmt.Println("Connected to Heartbeat")
        }
    default:
        switch env.Feed {
        case "heartbeat":
            fmt.Println("Live")
        }
    }
    return "No messages to Decode...", ""
}

func (c *WebSocket) Signature(message string) (string, string) {

    secret64, _ := base64.StdEncoding.DecodeString("rhsqfT66dxTF7g2O7/t5Cluubjw4MlEz1UoBrZBjf8JocQ/q49j9rH9m")

    hash := sha256.New()
    hash.Write([]byte(message))

    challenge256 := hash.Sum(nil)

    hmacHash := hmac.New(sha512.New, secret64)
    hmacHash.Write(challenge256)

    secretChallenge := hmacHash.Sum(nil)

    signed := base64.StdEncoding.EncodeToString(secretChallenge)
    return message, signed
}

//FillSubscribe populates message struct and sends out the JSON message
func (c *WebSocket) FillSubscribe(challenge string, signed string) error {

    fillMessage := map[string]interface{}{
        "event":              "subscribe",
        "feed":               "fills",
        "api_key":            "rhsqfT66dxTF7g2O7/t5Cluubjw4MlEz1UoBrZBjf8JocQ/q49j9rH9m",
        "original_challenge": challenge,
        "signed_challenge":   signed,
    }
    c.Conn.SetWriteDeadline(time.Now().Add(Wait))
    err := c.Conn.WriteJSON(fillMessage)
    if err != nil {
        log.Println("write:", err)
        return err
    }

    return err
}

Here is my main program:

package main

import (
    "fmt"
    "log"

    "github.com/Mjavala/KrakenAPI/websocket"
)

var message string
var signed string

func main() {

    ws, err := websocket.OpenWebSocket()
    if err != nil {
        log.Fatal(err)
    }

    ws.HeartBeat()
    ws.Challenge()

    fmt.Println(message, signed)

    for {
        // We first read in a raw message. An error here is a socket level
        // error.
        payload, err := ws.Next()
        if err != nil {
            log.Fatalf("socket error: %+v
", err)
        }

        log.Printf("recv: %s", payload)

        message, signed = ws.Decode(payload)
        if err != nil {
            log.Fatalf("decode error: %+v
", err)
        }
    }
}

I believe that even if the API Keys are wrong a return message should still be sent, as per the API; but instead I get that 1006 close frame.

I'm new to WebSockets. I'm able to get the challenge messaged and heartbeat subscription from the API, the problem is specific to the fill subscription.

Also if anyone wants to replicate this, I can give the full code/Git link.

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 求daily translation(DT)偏差订正方法的代码
    • ¥15 js调用html页面需要隐藏某个按钮
    • ¥15 ads仿真结果在圆图上是怎么读数的
    • ¥20 Cotex M3的调试和程序执行方式是什么样的?
    • ¥20 java项目连接sqlserver时报ssl相关错误
    • ¥15 一道python难题3
    • ¥15 牛顿斯科特系数表表示
    • ¥15 arduino 步进电机
    • ¥20 程序进入HardFault_Handler
    • ¥15 关于#python#的问题:自动化测试