这里相当新的地鼠。经验有限。
我正在阅读一本探索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>
答案 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)
}
}