dongyou2279
dongyou2279
2016-04-02 11:29

转到websocket jsonrpc浏览器连接关闭

已采纳

I have a WebSocket JSON-RPC server example that I want to use from a browser. When you access the URL "http:localhost:8080", the browser opens the WebSocket connection properly. But when the browser sends the WebSocket request, the server closes the WebSocket connection. I can't even see a trace of the RPC method being called on the server.

However, calling the server from a Go client works perfectly.

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)
}

Do you know what the problem could be?

Thank you very much.

Cheers

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

1条回答

  • duanjue7508 duanjue7508 5年前

    When the server application calls jsonrpc.ServeConn(ws.UnderlyingConn()) } the server is switching from the WebSocket protocol to the JSON-RPC protocol. The browser continues to use the WebSocket protocol. The connection is closed because one of the peers errors out reading a protocol that it does not expect.

    The problem does not happen with the Go client application because this application also switches from the WebSocket protocol to the JSON-RPC protocol.

    It is not possible to access the underlying network connection from a browser application.

    It is possible to use the net/rpc package with Codec written to use the WebSocket protocol. Another option is to write an adaptor to convert the message based WebSocket API to the stream expected by the net/rpc/jsonrpc server.

    点赞 评论 复制链接分享