golang gorilla websocket例子
WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。 在golang语言中,目前有两种比较常用的实现方式:一个是golang自带的库,另一个是gorilla,功能强大。 golang自带库的使用例子可参考以前的博文:Golang如何使用websocket 本文以gorilla为例,介绍websocket的使用。 下载gorilla# go get github.com/gorilla/websocket 下面例子中主要包括两部分,server和client。 serverserver端是一个HTTP 服务器,监听8080端口。 当接收到连接请求后,将连接使用的http协议升级为websocket协议。后续通信过程中,使用websocket进行通信。 对每个连接,server端等待读取数据,读到数据后,打印数据,然后,将数据又发送给client. server启动方式 # go run server.go server.go代码如下: // Copyright 2015 The Gorilla WebSocket Authors. All rights reserved. // 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> <html> <head> <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> <body> <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. <p> <form> <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:
非web clientclient启动后,首先连接server。 连接建立后,主routine每一秒钟向server发送消息(当前时间)。 另一个routine从server接收数据,并打印。 当client退出时,会向server发送关闭消息。接着,等待退出。 client启动方式 # go run client.go client代码如下: // Copyright 2015 The Gorilla WebSocket Authors. All rights reserved. // 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" "os/signal" "time" "github.com/gorilla/websocket" ) var addr = flag.String("addr","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 { _,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:
web clientweb client,也就是使用浏览器。 "Open",然后"send" server output:
参考百度百科 https://baike.baidu.com/item/WebSocket github https://github.com/gorilla/websocket doc https://godoc.org/github.com/gorilla/websocket example https://github.com/gorilla/websocket/blob/master/examples/ (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |