【问题标题】:Go websocket jsonrpc browser connection closeGo websocket jsonrpc 浏览器连接关闭
【发布时间】:2016-07-22 05:22:03
【问题描述】:

我有一个 WebSocket JSON-RPC 服务器示例,我想在浏览器中使用它。当您访问 URL“http:localhost:8080”时,浏览器会正确打开 WebSocket 连接。但是当浏览器发送 WebSocket 请求时,服务器会关闭 WebSocket 连接。我什至看不到服务器上调用的 RPC 方法的踪迹。

但是,从 Go 客户端调用服务器效果很好。

server.go

package main

import (
        "log"
        "net/http"
        "net/rpc"
        "net/rpc/jsonrpc"
        "github.com/gorilla/websocket"
)

type Service struct{}

func (t *Service) Echo(req *string, res *string) error {
        log.Printf("Service.Echo")
        *res = *req
        log.Printf("Service.Echo req:%s res:%s", *req, *res)
        return nil 
}

var upgrader = websocket.Upgrader{
        ReadBufferSize:  1024,
        WriteBufferSize: 1024,
}

func serveWS(w http.ResponseWriter, r *http.Request) {
        ws, err := upgrader.Upgrade(w, r, nil)
        defer ws.Close()


        if err != nil {
                log.Println(err)
                return
        }   
        jsonrpc.ServeConn(ws.UnderlyingConn())
}

func main() {
        rpc.Register(new(Service))
        http.Handle("/", http.FileServer(http.Dir("web")))
        http.HandleFunc("/ws", serveWS)
        http.ListenAndServe(":8080", nil)
}

web/index.html

<!DOCTYPE html>
<html lang="en">
<head>  
<script type="text/javascript">
    var ws = new WebSocket("ws://localhost:8080/ws");
    ws.onopen = function(ev){
        alert("open");
    }
    ws.onmessage = function(ev){
        alert("message");
    }
    ws.onclose = function(ev){
        alert("close");
    }   

    function send() {
        msg = {
                method: "Service.Echo",
                params: "hello",
                id: 0
        };
        var s = JSON.stringify(msg);
        alert(s);
        ws.send(s);
    }   
</script>
</head> 
<body>          
<button onclick='send()'>Send</button>
</body> 
</html>

client.go

package main

import (
        "log"
        "net/rpc/jsonrpc"
        "github.com/gorilla/websocket"
)

func main() {
        ws, _, err := websocket.DefaultDialer.Dial("ws://localhost:8080/ws", nil)
        if err != nil {
                log.Fatal("dial:", err)
        }
        defer ws.Close()

        client := jsonrpc.NewClient(ws.UnderlyingConn())

        req := "hello"
        var res string
        err = client.Call("Service.Echo", &req, &res)
        if err != nil {
                log.Fatal("Service.Echo error:", err)
        }
        log.Printf("Service.Echo: req:%s res:%s", req, res)
}

你知道问题可能是什么吗?

非常感谢。

干杯

【问题讨论】:

标签: go websocket json-rpc gorilla


【解决方案1】:

当服务器应用程序调用jsonrpc.ServeConn(ws.UnderlyingConn()) } 时,服务器正在从WebSocket 协议切换到JSON-RPC 协议。浏览器继续使用WebSocket 协议。连接已关闭,因为其中一个对等方错误地读取了它不期望的协议。

Go 客户端应用程序不会出现此问题,因为此应用程序也从 WebSocket 协议切换到 JSON-RPC 协议。

无法从浏览器应用程序访问底层网络连接。

可以使用带有Codec 的net/rpc 包来使用WebSocket 协议。另一种选择是编写一个适配器,将基于消息的 WebSocket API 转换为 net/rpc/jsonrpc 服务器期望的流。

【讨论】:

  • 好的,我明白了。但是,有没有办法从浏览器中使用 websocket jsonrpc 服务器?
  • 无法从浏览器使用 JSON-RPC 协议。
  • @Alvaro 您可以实现 Codec 以从浏览器使用 net/rpc 包。此外,交叉链接这些 Google 网上论坛帖子,这样人们就不会浪费时间回答这里所涵盖的内容。
  • 是的,编解码器似乎是我正在寻找的。我的最终目标只是通过 Websocket 连接发送 JSON-RPC 消息。你知道任何例子吗?
  • 编写一个适配器,将基于消息的 WebSocket API 转换为 net/rpc/json 服务器期望的流。或者,复制 net/rpc/jsonrpc server.go 并修改它以使用基于消息的 WebSocket API。
猜你喜欢
  • 2012-07-30
  • 2018-11-26
  • 2019-01-17
  • 2013-01-11
  • 1970-01-01
  • 2018-09-11
  • 1970-01-01
  • 1970-01-01
  • 2015-11-11
相关资源
最近更新 更多