dongwen2162 2016-08-10 13:27
浏览 702
已采纳

尝试进行Websocket连接时出现意外的响应代码200

Fairly new gopher here. Limited experience.

I am going through a book that explores websockets and I hit a dead end. I have assembled a simple chat app with the examples from the book and when I run it I hit the following error:

WebSocket connection to 'ws://localhost:5000/room' failed: Error during WebSocket handshake: Unexpected response code: 200

Does anybody know what causes this?

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条回答 默认 最新

  • dongyuqi3808 2016-08-10 13:56
    关注

    The problem is that the room handler is not registered with the mux. All requests are served by the handler for / in main.go.

    To fix this issue, add code to intialize the room value and register it with the 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)
      }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。