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代码如下:

// 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:

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代码如下:

// 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", "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

doc

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

example

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

golang gorilla websocket例子的更多相关文章

  1. golang实现WebSocket的商业化使用的开发逻辑(1)

    WebSocket是什么 WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议.其最大特点之一就是:服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对 ...

  2. golang之websocket 源码分析

    下载go的websocket包. 1. 通过google官方的方法, 需要hg来同步代码. 由于墙的原因, 还需要设置代理. 比较麻烦 2. http://gopm.io/ 通过该网站下载, 这是go ...

  3. 带ssl的websocket例子

    还是在那个websocket_demo的例子 rebar-creator create-app websocket_demo tree一下看看大概目录 ├── cert │   ├── cowboy- ...

  4. golang 移动应用例子 example/basic 源码框架分析

    条件编译 我们在源码中可以看到2个文件: main.go 和 main_x.go 这两个包名都是 package main , 都有 main 函数. 不会冲突么? 答案是不会的, main_x.go ...

  5. (网页)websocket例子

    转载自博客园张果package action; import javax.websocket.CloseReason; import javax.websocket.OnClose; import j ...

  6. 基于netty的websocket例子

    nettyServer package com.atguigu.netty.websocket; import javax.annotation.PostConstruct; import org.s ...

  7. erlang的websocket例子

    创建工程 rebar-creator create-app websocket_demo 文件列表 route_helper.erl -module(route_helper). -export([g ...

  8. Springboot WebSocket例子

    Springboot整合WebSocket 1.application.properties #设置服务端口号 server.port=8080 #thymeleaf配置 #是否启用模板缓存. spr ...

  9. golang LMDB入门例子——key range查询

    如下,使用gomb库 package main import ( "bytes" "fmt" "io/ioutil" "os&qu ...

随机推荐

  1. 【Python】xml遍历练习

      <?xml version="1.0" encoding="utf-8" ?> <!--this is a test about xml. ...

  2. nodejs的express框架

    介绍: Express是由路由和中间件构成一个的nodejs的一种web应用框架; 功能: 可以设置中间件来响应 HTTP 请求. 定义了路由表用于执行不同的 HTTP 请求动作. 可以通过向模板传递 ...

  3. simhash

    1,SimHash https://yanyiwu.com/work/2014/01/30/simhash-shi-xian-xiang-jie.html 64位Hash为什么海明距离选3? http ...

  4. vmware安装centos问题

    * 选择安装后,一直黑屏 重新启动电脑,在启动界面进入BIOS设置,找到Intel (R) Virtualization Technology,设置成Enabled,保存设置以后重新启动电脑,问题解决 ...

  5. 全局(Global) 与本地(Local)索引的区别

    一.定义说明 oracle数据库中,存在多种对象,最常见的表和索引,索引的目的是为了加快查询:oracle建议一个表>2g时,就建议进行分区,分区表的好处此处省略,分区表有维护操作,但是某些维护 ...

  6. Vim正则表达式匹配替换字符串

    /********************************************************************** * Vim正则表达式匹配替换字符串 * 说明: * 用V ...

  7. javascript的this多种场景用法

    作者:刘志祥 时间:2017.11.10 参考:阮一峰的官方网站 this 是javaScript中的一个关键字,只能在函数内使用.随着场合的不同,this的值会发生变化. 1. 单纯的全局函数调用, ...

  8. s21day01 python笔记

    s21day01 python笔记 一.计算机基础 计算机的初步认识 用户:人 软件:QQ.浏览器等 解释器/编译器/虚拟机:java解释器.python解释器等 操作系统 硬件:CPU.内存.硬盘. ...

  9. 如何更改Apache的根目录指向

    更改Apache的默认网站根目录地址方法如下: 0,先找到主目录下的apache文件,然后进行下面操作 1.找到 DocumentRoot “X:/Apache/htdocs” 将“X:/Apache ...

  10. document.write中输出html标签用法

    输出HTML标签,只需将标签写入双引号: 示例:在网页中输出<p>革命还在继续</p> document.write("<p style='border:1px ...