添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。
WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范。

在golang语言中,目前有两种比较常用的实现方式:一个是golang自带的库,另一个是gorilla,功能强大。

golang自带库的使用例子可参考以前的博文: Golang如何使用websocket

本文以gorilla为例,介绍websocket的使用。

下载gorilla

# go get github.com/gorilla/websocket

下面例子中主要包括两部分,server和client。
client部分又包括:web client(浏览器)和非web client。

server

server端是一个HTTP 服务器,监听8080端口。

当接收到连接请求后,将连接使用的http协议升级为websocket协议。后续通信过程中,使用websocket进行通信。

对每个连接,server端等待读取数据,读到数据后,打印数据,然后,将数据又发送给client.

server启动方式

# go run server.go

server.go代码如下:

// Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build ignore package main import ( "flag" "html/template" "log" "net/http" "github.com/gorilla/websocket" var addr = flag.String("addr", "localhost:8080", "http service address") var upgrader = websocket.Upgrader{} // use default options func echo(w http.ResponseWriter, r *http.Request) { c, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Print("upgrade:", err) return defer c.Close() for { mt, message, err := c.ReadMessage() if err != nil { log.Println("read:", err) break log.Printf("recv: %s", message) err = c.WriteMessage(mt, message) if err != nil { log.Println("write:", err) break func home(w http.ResponseWriter, r *http.Request) { homeTemplate.Execute(w, "ws://"+r.Host+"/echo") func main() { flag.Parse() log.SetFlags(0) http.HandleFunc("/echo", echo) http.HandleFunc("/", home) log.Fatal(http.ListenAndServe(*addr, nil)) var homeTemplate = template.Must(template.New("").Parse(` <!DOCTYPE html> <meta charset="utf-8"> <script> window.addEventListener("load", function(evt) { var output = document.getElementById("output"); var input = document.getElementById("input"); var ws; var print = function(message) { var d = document.createElement("div"); d.innerHTML = message; output.appendChild(d); document.getElementById("open").onclick = function(evt) { if (ws) { return false; ws = new WebSocket("{{.}}"); ws.onopen = function(evt) { print("OPEN"); ws.onclose = function(evt) { print("CLOSE"); ws = null; ws.onmessage = function(evt) { print("RESPONSE: " + evt.data); ws.onerror = function(evt) { print("ERROR: " + evt.data); return false; document.getElementById("send").onclick = function(evt) { if (!ws) { return false; print("SEND: " + input.value); ws.send(input.value); return false; document.getElementById("close").onclick = function(evt) { if (!ws) { return false; ws.close(); return false; </script> </head> <table> <tr><td valign="top" width="50%"> <p>Click "Open" to create a connection to the server, "Send" to send a message to the server and "Close" to close the connection. You can change the message and send multiple times. <button id="open">Open</button> <button id="close">Close</button> <p><input id="input" type="text" value="Hello world!"> <button id="send">Send</button> </form> </td><td valign="top" width="50%"> <div id="output"></div> </td></tr></table> </body> </html> `))

server output:

recv: 2018-10-20 17:09:12.497129965 +0800 CST m=+1.010137585
recv: 2018-10-20 17:09:13.495602484 +0800 CST m=+2.008641088
recv: 2018-10-20 17:09:14.49401062 +0800 CST m=+3.007080206
recv: 2018-10-20 17:09:15.497114615 +0800 CST m=+4.010215329
recv: 2018-10-20 17:09:16.494394706 +0800 CST m=+5.007526368
read: websocket: close 1000 (normal)

非web client

client启动后,首先连接server。

连接建立后,主routine每一秒钟向server发送消息(当前时间)。

另一个routine从server接收数据,并打印。

当client退出时,会向server发送关闭消息。接着,等待退出。

client启动方式

# go run client.go

client代码如下:

// Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build ignore package main import ( "flag" "log" "net/url" "os/signal" "time" "github.com/gorilla/websocket" var addr = flag.String("addr", "localhost:8080", "http service address") func main() { flag.Parse() log.SetFlags(0) interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt) u := url.URL{Scheme: "ws", Host: *addr, Path: "/echo"} log.Printf("connecting to %s", u.String()) c, _, err := websocket.DefaultDialer.Dial(u.String(), nil) if err != nil { log.Fatal("dial:", err) defer c.Close() done := make(chan struct{}) go func() { defer close(done) for { _, message, err := c.ReadMessage() if err != nil { log.Println("read:", err) return log.Printf("recv: %s", message) }() ticker := time.NewTicker(time.Second) defer ticker.Stop() for { select { case <-done: return case t := <-ticker.C: err := c.WriteMessage(websocket.TextMessage, []byte(t.String())) if err != nil { log.Println("write:", err) return case <-interrupt: log.Println("interrupt") // Cleanly close the connection by sending a close message and then // waiting (with timeout) for the server to close the connection. err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) if err != nil { log.Println("write close:", err) return select { case <-done: case <-time.After(time.Second): return

client output:

connecting to ws://localhost:8080/echo
recv: 2018-10-20 17:09:12.497129965 +0800 CST m=+1.010137585
recv: 2018-10-20 17:09:13.495602484 +0800 CST m=+2.008641088
recv: 2018-10-20 17:09:14.49401062 +0800 CST m=+3.007080206
recv: 2018-10-20 17:09:15.497114615 +0800 CST m=+4.010215329
recv: 2018-10-20 17:09:16.494394706 +0800 CST m=+5.007526368
^Cinterrupt
read: websocket: close 1000 (normal)

web client

web client,也就是使用浏览器。
在浏览器中输入http://127.0.0.1:8080

“Open”,然后"send"

server output:

recv: Hello world!

https://baike.baidu.com/item/WebSocket

github

https://github.com/gorilla/websocket

https://godoc.org/github.com/gorilla/websocket

example

https://github.com/gorilla/websocket/blob/master/examples/

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范。在golang语言中,目前有两种比较常用的实现方式:一个是golang自带的库,另一个是gorilla,功能强大。golang自带库的使用例子...
最近写了一个chrome的websocket extension, server端用的是Netty, 后来发现golang 实现websocket 非常简单,高效, 下面是例子, 简单实现了用户登录,广播,相当于聊天室! package main import ( "code.google.com/p/go.net/websocket" "html/template" "log"
func ping(c *gin.Context) { //升级get请求为webSocket协议 ws, err := upGrader.Upgrade(c.Writer, c.Request, nil) if err != nil {
最近在做websocket,需要用到这些,查资料记录下(官网:https://developer.mozilla.org/zh-CN/docs/Web/API/CloseEvent)。 CloseEvent.code只读 返回一个 unsigned short 类型的数字, 表示服务端发送的关闭码, 以下为已分配的状态码. 0–999