尝试websocket连接时出现意外的响应代码200

时间:2016-08-10 13:27:43

标签: go websocket

这里相当新的地鼠。经验有限。

我正在阅读一本探索websockets的书,我走到了尽头。我已经用书中的例子组装了一个简单的聊天应用程序,当我运行它时,我遇到了以下错误:

  

与'ws:// localhost:5000 / room'的WebSocket连接失败:错误   在WebSocket握手期间:意外的响应代码:200

有人知道是什么原因引起的吗?

main.go

package main

import (
    "html/template"
    "log"
    "net/http"
    "path/filepath"
    "sync"
)

type templateHandler struct {
    //once is an object that will perform exactly one action
    once     sync.Once
    filename string
    templ    *template.Template
}

func (t *templateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    //this function call will be executed only once
    t.once.Do(func() {
        t.templ = template.Must(template.ParseFiles(filepath.Join("templates", t.filename)))
        log.Println("one time")
    })
    t.templ.Execute(w, nil)
}

func main() {
    http.Handle("/", &templateHandler{filename: "chat.html"})
    if err := http.ListenAndServe(":5000", nil); err != nil {
        log.Fatal("ListenAndServe", err)
    }
}

client.go

package main

//Notes on channels
//read from channel x to a
//a := <- x
//write 5 to channel x
//x <- 5

import (
    "github.com/gorilla/websocket"
)

//client represents a single chatting user.

type client struct {
    //client represents a single chatting user
    socket *websocket.Conn
    //sent is a channel on which messages are sent
    send chan []byte
    //room is the room this client is chatting in
    room *room
}

func (c *client) read() {
    for {
        //if err is nil after the execution of ReadMessage()
        //execute the line between the braces
        if _, msg, err := c.socket.ReadMessage(); err == nil {
            c.room.forward <- msg
        } else {
            break
        }
    }
    c.socket.Close()
}

func (c *client) write() {
    for msg := range c.send {
        if err := c.socket.WriteMessage(websocket.TextMessage, msg); err != nil {
            break
        }
    }
    c.socket.Close()
}

room.go

package main

import (
    "log"
    "net/http"

    "github.com/gorilla/websocket"
)

type room struct {
    //forward is a channel that holds incoming messages
    //that should be forwarded to other clients
    forward chan []byte
    //join is a channel for clients wishing to join the room
    join chan *client
    //leave is a channel for clients wishing to leave the room.
    leave chan *client
    //clients holds al the current clients in this room.
    clients map[*client]bool
}

func (r *room) run() {
    for {
        select {
        case client := <-r.join:
            //joining
            r.clients[client] = true
        case client := <-r.leave:
            //leaving
            delete(r.clients, client)
            close(client.send)
        case msg := <-r.forward:
            //forward message to all clients
            for client := range r.clients {
                select {
                case client.send <- msg:
                default:
                    //failed to send
                    delete(r.clients, client)
                    close(client.send)
                }
            }
        }
    }
}

const (
    socketBufferSize  = 1024
    messageBufferSize = 256
)

//in order for the browser to switch to the websocket
//protocol a header with an upgrade request from http
//to websocket must be sent
var upgrader = &websocket.Upgrader{
    ReadBufferSize:  socketBufferSize,
    WriteBufferSize: socketBufferSize,
}

func (r *room) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    socket, err := upgrader.Upgrade(w, req, nil)
    if err != nil {
        log.Fatal("ServeHTTP:", err)
        return
    }
    client := &client{
        socket: socket,
        send:   make(chan []byte, messageBufferSize),
        room:   r,
    }

    r.join <- client
    defer func() { r.leave <- client }()
    go client.write()
    client.read()
}

chat.html

<!DOCTYPE html>
<html>
<head>
  <title>Chat</title>
<style>
input {display:block;}
ul{list-style:none;}
</style>

</head>
<body>
    <ul id="messages"></ul>
    <form id="chatbox">
        <textarea></textarea>
        <input type="submit" value="Send" />
    </form>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
    </script>

    <script>
$(function(){
    var socket = null;
    var msgBox = $("#chatbox textarea");
    var messages = $("#messages");
    $("#chatbox").submit(function(){
        if (!msgBox.val()) return false;
        if (!socket) {
            alert("Error: There is no socket connection.");
            return false;
        }
        socket.send(msgBox.val());
        msgBox.val("");
        return false;
    });
    if (!window["WebSocket"]) {
        alert("Error: Your browser does not support web sockets.")
    }else {
        socket = new WebSocket("ws://localhost:5000/room");
        socket.onclose = function() {
            alert("Connection has been closed.");
        }
        socket.onmessage = function(e) {
            messages.append($("<li>").text(e.data));
        }
    }
});
    </script>
</body>
</html>

1 个答案:

答案 0 :(得分:2)

问题是房间处理程序未在多路复用器中注册。所有请求均由/ in.main.go中的处理程序提供。

要解决此问题,请添加代码以初始化room值并将其注册到mox:

func main() {
  http.Handler("/room", &room{
     forward: make(chan []byte),
     join: make(chan *client),
     leave: make(chan *client),
     clients: make(map[*client]bool),
  })
  http.Handle("/", &templateHandler{filename: "chat.html"})
  if err := http.ListenAndServe(":5000", nil); err != nil {
    log.Fatal("ListenAndServe", err)
  }
}