🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## websocket握手 * WebSocket是HTML5中的协议,支持持久连接 * WebSocket 是一个双向通信协议,它在握手阶段采用 HTTP/1.1 协议(暂时不支持 HTTP/2) * WebSocket 提供两种协议:不加密的 ws:// 和 加密的 wss:// ## Websocket API websocket 客户端 ```jsx <!--client.html--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello</title> </head> <body> <script type="text/javascript"> var sock = null; var wsuri = "ws://127.0.0.1:1234"; window.onload = function () { console.log("onload"); sock = new WebSocket(wsuri); sock.onopen = function () { console.log("connected to " + wsuri); } sock.onclose = function (e) { console.log("connection closed (" + e.code + ")"); } sock.onmessage = function (e) { console.log("message received: " + e.data); } }; function send() { var msg = document.getElementById('message').value; sock.send(msg); }; </script> <h1>WebSocket Echo Test</h1> <form> <p> Message: <input id="message" type="text" value="Hello, world!"> </p> </form> <button onclick="send();">Send Message</button> </body> </html> ``` ## 握手过程 1 首先客户端向服务端发起一个特殊的 HTTP 请求,其消息头如下: ``` GET ws://127.0.0.1:1234/ HTTP/1.1 # 请求行 Host: 127.0.0.1:1234 Connection: Upgrade Pragma: no-cache Cache-Control: no-cache User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36 Upgrade: websocket #服务器支持WebSocket协议它将同意 Origin: http://localhost:63342 #用于防止未认证的跨域脚本使用浏览器 websocket api 与服务端进行通信 Sec-WebSocket-Version: 13 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 #16bits 编码得到的 base64 串 Sec-WebSocket-Key: FRzOf/abiWUYuiAE/QOE5Q== Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits #可选:子协议协商字段 Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 ``` 2.如果服务端支持该版本的 WebSocket,会返回 101 响应,响应标头如下: ``` HTTP/1.1 101 Switching Protocols # 状态行 Upgrade: websocket # required Connection: Upgrade # required Sec-WebSocket-Accept: 17QAL00Qp1wMedfVeqFk0K1UwqQ= #required,加密后的 Sec-WebSocket-Key Sec-WebSocket-Protocol: chat #表明选择的子协议 ``` ## 提供一个Golang版本的websocket Server ``` //Server.go package main import ( "fmt" "log" "net/http" "golang.org/x/net/websocket" ) func Echo(ws *websocket.Conn) { var err error for { var reply string if err = websocket.Message.Receive(ws, &reply); err != nil { fmt.Println("Can't receive") break } fmt.Println("Received back from client: " + reply) msg := "Received: " + reply fmt.Println("Sending to client: " + msg) if err = websocket.Message.Send(ws, msg); err != nil { fmt.Println("Can't send") break } } } func main() { http.Handle("/", websocket.Handler(Echo)) if err := http.ListenAndServe(":1234", nil); err != nil { log.Fatal("ListenAndServe:", err) } } ``` 启动服务 ``` $ go run Server.go ``` 启动客户端, 点击`Send Message`, client console ``` message received: Received: Hello, world! ``` Server output ``` Received back from client: Hello, world! Sending to client: Received: Hello, world! ```