Reference resources
https://github.com/ukai/go-websocket-sample/blob/master/websocket_echo_sample.go
https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/08.2.md
WebSocket is an important feature of HTML5. It implements remote socket based on browser. It enables full duplex communication between browser and server, which is supported by many browsers (Firefox, Google Chrome and Safari).
Websocket uses some special headers, so that the browser and the server can establish a connection channel between the browser and the server only need to make a handshake. And this connection will remain active. It solves the problem of real-time web. The websocket server can push data to the web client.
The initial input for WebSocket URL is ws: / /, or wss: / / (on SSL). The following figure shows the communication process of WebSocket. An HTTP handshake with a specific header is sent to the server, and then a socket can be used by the server or the client through JavaScript, which can be used to receive data asynchronously through the event handle.
Example
The reference is simplified and optimized, and the test code is written. The browser is shown as follows
Server side
package main import ( "fmt" "golang.org/x/net/websocket" "html/template" "io" "log" "net/http" ) func Copy(ws *websocket.Conn) { fmt.Printf("copyServer %#v\n", ws.Config()) io.Copy(ws, ws) //websocket.Conn implements Read() and Write(), so you can Copy directly. At this time, the received content will be blocked and copied continuously. fmt.Println("copyServer finished") } func ReadWrite(ws *websocket.Conn) { fmt.Printf("readWriteServer %#v\n", ws.Config()) for { buf := make([]byte, 100) n, err := ws.Read(buf) if err != nil { fmt.Println(err) break } fmt.Printf("recv:%q\n", buf[:n]) n, err = ws.Write(buf[:n]) if err != nil { fmt.Println(err) break } fmt.Printf("send:%q\n", buf[:n]) } fmt.Println("readWriteServer finished") } // When receiving string, websocket.message.receive (WS, & buf) and ws.Read(buf) functions similarly. Sending the same reason func RecvSend(ws *websocket.Conn) { fmt.Printf("recvSendServer %#v\n", ws) for { var buf string err := websocket.Message.Receive(ws, &buf) if err != nil { fmt.Println(err) break } fmt.Printf("recv:%q\n", buf) err = websocket.Message.Send(ws, buf) if err != nil { fmt.Println(err) break } fmt.Printf("send:%q\n", buf) } fmt.Println("recvSendServer finished") } // When receiving [] byte s, websocket.message.receive (WS, & buf) can receive and send binary files func RecvSendBinary(ws *websocket.Conn) { fmt.Printf("recvSendBinaryServer %#v\n", ws) for { var buf []byte err := websocket.Message.Receive(ws, &buf) if err != nil { fmt.Println(err) break } fmt.Printf("recv:%#v\n", buf) err = websocket.Message.Send(ws, buf) if err != nil { fmt.Println(err) break } fmt.Printf("send:%#v\n", buf) } fmt.Println("recvSendBinaryServer finished") } type T struct { Msg string `json:"msg"` Path string `json:"path"` } func Json(ws *websocket.Conn) { fmt.Printf("jsonServer %#v\n", ws.Config()) for { var msg T err := websocket.JSON.Receive(ws, &msg) if err != nil { fmt.Println(err) break } fmt.Printf("recv:%#v\n", msg) err = websocket.JSON.Send(ws, msg) if err != nil { fmt.Println(err) break } fmt.Printf("send:%#v\n", msg) } fmt.Println("jsonServer finished") } func web(w http.ResponseWriter, r *http.Request) { t, _ := template.ParseFiles("main/websocket.html") t.Execute(w, nil) } func main() { //Receive the routing address of websocket http.Handle("/copy", websocket.Handler(Copy)) http.Handle("/readWrite", websocket.Handler(ReadWrite)) http.Handle("/recvSend", websocket.Handler(RecvSend)) http.Handle("/recvSendBinary", websocket.Handler(RecvSendBinary)) http.Handle("/json", websocket.Handler(Json)) //html page http.HandleFunc("/web", web) if err := http.ListenAndServe(":1234", nil); err != nil { log.Fatal("ListenAndServe:", err) } }
HTML file
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>websocket test</title> </head> <body> <h1>select method</h1> <form> <input type="radio" name="route" value="ws://127.0.0.1:1234/copy">copy<br> <input type="radio" name="route" value="ws://127.0.0.1:1234/readWrite">readWrite<br> <input type="radio" name="route" value="ws://127.0.0.1:1234/recvSend">recvSend<br> <input type="radio" name="route" value="ws://127.0.0.1:1234/recvSendBinary">recvSendBinary<br> <input type="radio" name="route" value="ws://127.0.0.1:1234/json">json<br> </form> <button οnclick="connect()">Connect</button> <button οnclick="disconnect()">To break off</button> <h1>send</h1> <input id="message" type="text" value="Hello, world!"> <button οnclick="send()">Send Message</button> <h1>receive</h1> <input id="receive" readonly> </body> <script type="text/javascript"> let sock = null; function connect() { let url = null; let routes = document.getElementsByName("route"); for (let j = 0; j < routes.length; j++){ if (routes[j].checked){ url = routes[j].value } if (url === "ws://127.0.0.1:1234/json"){ document.getElementById('message').value = JSON.stringify({msg: 'Hello', path: 'localhost'}) } } if (url != null){ console.log("url:" + url); sock = new WebSocket(url); sock.onopen = function () { console.log("connected to " + url); }; sock.onmessage = function (e) { document.getElementById('receive').value = e.data; }; sock.onclose = function (e) { console.log("connection: " + url + " closed(" + e.code + ")") }; } } function disconnect() { sock.close(); } function send() { let msg = document.getElementById('message').value; sock.send(msg); } </script> </html>