golang开发 gorilla websocket的使用
很多APP都需要主动向用户推送消息,这就需要用到长连接的服务,即我们通常提到的websocket,同样也是使用socket服务,通信协议是基本类似的,在go中用的最多的、也是最简单的socket服务就是gorilla/websocket,它有21.1K的star,足以说明它的受欢迎程度, 它的github地址是 https://github.com/gorilla/websocket,我们的长连接服务也是通过gorilla/websocket改造出来的。
websocket的简单使用
我们使用的版本是1.3.0,首先下载websocket
go get github.com/gorilla/websocket@v1.3.0
把websocket/examples/echo下面的 client.go server.go 现在下来拷贝到项目里面。
https://github.com/gorilla/websocket/blob/v1.3.0/examples/echo/server.go
https://github.com/gorilla/websocket/blob/v1.3.0/examples/echo/client.go
在一个终端执行 websocket 服务
go run server.go
recv: 2024-04-16 15:09:45.805438 +0800 CST m=+1.007536889
recv: 2024-04-16 15:09:46.805425 +0800 CST m=+2.007517605
recv: 2024-04-16 15:09:47.806274 +0800 CST m=+3.008359325
recv: 2024-04-16 15:09:48.80495 +0800 CST m=+4.007028866
recv: 2024-04-16 15:09:49.805743 +0800 CST m=+5.007816108
recv: 2024-04-16 15:09:50.806087 +0800 CST m=+6.008153310
recv: 2024-04-16 15:09:51.805348 +0800 CST m=+7.007407266
再打开一个终端执行 go run client.go,充当客户端
connecting to ws://localhost:8080/echo
recv: 2024-04-16 15:09:45.805438 +0800 CST m=+1.007536889
recv: 2024-04-16 15:09:46.805425 +0800 CST m=+2.007517605
recv: 2024-04-16 15:09:47.806274 +0800 CST m=+3.008359325
recv: 2024-04-16 15:09:48.80495 +0800 CST m=+4.007028866
recv: 2024-04-16 15:09:49.805743 +0800 CST m=+5.007816108
recv: 2024-04-16 15:09:50.806087 +0800 CST m=+6.008153310
recv: 2024-04-16 15:09:51.805348 +0800 CST m=+7.007407266
我们看看这个简单的例子。
client.go
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
}
}
go func() 的 c.ReadMessage 不停的从socket里面读取数据并且打印。
for 循环不停的从1秒的定时器里面读取时间,写到socket
server.go
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
}
}
for c.ReadMessage 循环不停的从 socket读取数据,把数据打印之后,又写给客户端。
这是大致的websocket 客户端与服务端通信的简单例子。
改成自定义的协议
我们使用二进制数据流,自定义的协议是这样的,
先是无符号的 uint 占4个字节,表示行为逻辑,比如111-获取信息, 110- 加好友等等
后面是具体的数据,跟HTTP请求的GET或者POST参数类似,具体数据格式定义好就行,比如可以使用JSON数据、可以使用RPC定义好的数据格式
修改完之后 client.go 代码是这样的
for {
select {
case <-done:
return
case <-ticker.C:
buf := bytes.NewBuffer([]byte{})
binary.Write(buf, binary.BigEndian, uint32(110))
binary.Write(buf, binary.BigEndian, []byte("我们都好"))
err := c.WriteMessage(websocket.BinaryMessage, buf.Bytes())
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
}
}
主要是这个
buf := bytes.NewBuffer([]byte{})
binary.Write(buf, binary.BigEndian, uint32(110))
binary.Write(buf, binary.BigEndian, []byte("我们都好"))
创建一个bytes Buffer
写入一个uint32,占4个字节,表示行为逻辑
写入行为逻辑具体的数据
以上采用大端通信
修改之后的 server.go
for {
mt, message, err := c.ReadMessage()
if err != nil {
log.Println("read:", err)
break
}
log.Println("messagetype:%d", mt)
log.Println("messagelen:%d", len(message))
log.Println("messagetype:%d", binary.BigEndian.Uint32(message[0:4]))
log.Println("recv: %s", string(message[4:]))
err = c.WriteMessage(mt, message)
if err != nil {
log.Println("write:", err)
break
}
}
mt websocket 类型
TextMessage = 1 文本类型传传输
BinaryMessage = 2 字节类型传输
从socket里面获取到message之后
先取前4个字节,表示逻辑行为
再取剩余的字节,表示行为逻辑需要的参数
我们重新执行一下,server.go 和 client.go
go run client.go
connecting to ws://localhost:8080/echo
recv: n我们都好
recv: n我们都好
go run server.go
messagetype:%d 2
messagelen:%d 16
messagetype:%d 110
recv: %s 我们都好
messagetype=2表示二进制通信
message长度是16,前四个字节是无符号整形,四个汉字占12个字节,一共16个字节,无符号uint是110表示加好友。
这就是一个简单自定义协议的socket服务。
如果有需要登录鉴权的话,在server.go中可以从r *http.Request 获取header或者cookie,进行登录鉴权验证。
生产的部署
因为是 websocket 协议,如果有代理服务器的话,需要在各代理服务器上的Nginx做协议升级,将HTTP 升级为 websocket ,比如下面的代理服务器。
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
location /serv/ {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_connect_timeout 3;
proxy_redirect off;
proxy_read_timeout 3600;
proxy_send_timeout 3600;
proxy_pass http://push_web/serv/;
}
}
golang开发 gorilla websocket的使用的更多相关文章
- golang gorilla websocket例子
WebSocket协议是基于TCP的一种新的网络协议.它实现了浏览器与服务器全双工(full-duplex)通信--允许服务器主动发送信息给客户端. WebSocket通信协议于2011年被IETF定 ...
- miniblink+golang开发windows gui应用
golang的优点自不必说了,这么好的语言怎么能缺少界面库呢?所以我使用miniblink开发了一个可以用html,css,js开发界面的浏览器,通过它你能为你的golang开发简单的界面.说白了其实 ...
- Golang 开发技能图谱
# Golang 开发技能图谱 ## Go 语言环境搭建- Go 安装- GOPATH 与工作空间- Go 命令- Go开发工具 ## GO 语言编程基础- 关键词和语法(Language Synta ...
- 使用golang 开发的 andriod应用
最近在捣鼓一个东东,就是使用golang开发andriod应用.说起来简单操作起来还挺麻烦,中间又学习了很多东西.比如ubuntu,docker,angular,ionic,jquery mobile ...
- golang开发android环境搭建_window
golang开发android环境搭建介绍 一 安装依赖软件: git:版本管理 go: go开发环境(版本>=1.5),可直接下载window版的go安装包. android studio: ...
- Windows下visual studio code搭建golang开发环境
Windows下visual studio code搭建golang开发环境 序幕 其实环境搭建没什么难的,但是遇到一些问题,主要是有些网站资源访问不了(如:golang.org),导致一些包无法安装 ...
- linux golang开发环境配置(离线方式)
<获取开发工具> 到https://www.golangtc.com/download 下载安装包, 根据自己的系统选择合适的开发包,这里选择go.1.9.2.linux-amd6 ...
- Linux下golang开发环境搭建
对于golang开发来说,Windows下可以用vscode或者liteide都不错,但是Linux下的开发也就只有vim了,所以怎么搞笑的利用vim进行golang开发呢? 参考官方推荐的一个插件: ...
- window / Linux 下 Golang 开发环境的配置
一直专注于使用python语言进行程序开发,但是却又一直被它的性能问题所困扰,直到遇到了天生支持高并发的Golang,这似乎也成了学习go语言最理所当然的理由.下面介绍下Go语言开发环境搭建的步骤: ...
- Golang开发环境搭建-Vim篇
一.一个干净的环境 找个干净的基础环境,方便确认每个搭建步骤后的效果: Ubuntu 14.04 x86_64 vim version 7.4.52 go version go1.4beta1 lin ...
随机推荐
- POJ2251 基础bfs
题目: 你进入了一个3D的宝藏地宫中探寻宝藏到了宝藏,你可以找到走出地宫的路带出宝藏,或者使用炉石空手回家. 地宫由立方体单位构成,立方体中不定会充满岩石.向上下前后左右移动一个单位需要一分钟.你不能 ...
- 深入理解DES算法:原理、实现与应用
title: 深入理解DES算法:原理.实现与应用 date: 2024/4/14 21:30:21 updated: 2024/4/14 21:30:21 tags: DES加密 对称加密 分组密码 ...
- python实现不同颜色气球隔开摆放,并且提示不能摆放的情况
这个是一位隐秘人物让我做的一道题(如标题),我也分享出来了. 首先是成品展示(暂时没有做成可视化界面的样子): 我做的是把所有的气球录入进来,然后利用基础数据结构(字典,数据等)排序等,由于我是初学, ...
- 暑期集训 Day5 —— 模拟赛复盘
${\color{Green} \mathrm{Problem\ 1 :选数 }} $ 签到题,一眼二分,但是打模板时死循环了: while(L<R){ int mid=(L+R)>> ...
- 云原生DevOps的5步升级路径
简介: 究竟什么是云原生DevOps呢?我们认为:云原生DevOps是充分利用云原生基础设施,基于微服务/无服务架构体系和开源标准,语言和框架无关,具备持续交付和智能自运维能力,从而做到比传统DevO ...
- Quick BI产品核心功能大图(六)开放集成
简介:企业想要拥有领先的数据分析能力,自研往往需要投入巨大的人力和财力. Quick BI作为唯一一个连续两年入选Gartner魔力象限的中国BI产品,具备强大的全链路开放集成能力,可以轻松的与企业 ...
- 快速界定故障:Socket Tracer网络监控实践
简介: Socket Tracer定位是传输层(Socket&TCP)的指标采集工具,通过补齐网络监控的这部分盲区,来达到快速界定网络问题的目标. 作者 | 四忌 来源 | 阿里技术公 ...
- 延迟绑定与retdlresolve
延迟绑定与retdlresolve 我们以前在ret2libc的时候,我们泄露的libc地址是通过延迟绑定实现的,我们知道,在调用libc里面的函数时候,它会先通过plt表和gor表绑定到,函数真实地 ...
- [FAQ] GitHub 开启二次验证之后,如何通过 https clone 项目 ?
在 Github Personal Access Tokens 页面,点击生成一个新的 tokon. 此时使用这个 token 作为用户的密码来 clone 项目.
- WPF 使用 Silk 的 Direct2D 入门
在上一篇博客的基础上,使用 dotnet 基金会新开源的 Silk.NET 库,让 Silk.NET 创建的 DX 设备和 WPF 对接渲染.接下来本文将告诉大家如何使用 Silk.NET 提供的 D ...