[golang]gin框架接收websocket通信
前言
WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket让客户端和服务端之间的数据交换变得非常简单,且允许服务器主动向客户端推送数据,并且之后客户端和服务端所有的通信都依靠这个专用协议进行。
本文使用gin框架编写服务端应用,配置路由接收websocket请求并处理。同时实现一个websocket命令行客户端用于与服务端通信。
服务端
下面代码示例中,使用gin创建一个应用,并将自定义函数WebSocketHandler()注册到/ws路由。WebSocketHandler()功能非常简单,客户端发送什么就原样返回什么。
package main
import (
"fmt"
"time"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
)
func WebSocketHandler(c *gin.Context) {
// 获取WebSocket连接
wsUpgrader := websocket.Upgrader{
HandshakeTimeout: time.Second * 10,
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
ws, err := wsUpgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
fmt.Println(err)
return
}
defer ws.Close()
// 处理WebSocket消息
for {
messageType, p, err := ws.ReadMessage()
if err != nil {
fmt.Println(err)
return
}
switch messageType {
case websocket.TextMessage:
fmt.Printf("处理文本消息, %s\n", string(p))
ws.WriteMessage(websocket.TextMessage, p)
// c.Writer.Write(p)
case websocket.BinaryMessage:
fmt.Println("处理二进制消息")
case websocket.CloseMessage:
fmt.Println("关闭websocket连接")
return
case websocket.PingMessage:
fmt.Println("处理ping消息")
ws.WriteMessage(websocket.PongMessage, []byte("ping"))
case websocket.PongMessage:
fmt.Println("处理pong消息")
ws.WriteMessage(websocket.PongMessage, []byte("pong"))
default:
fmt.Printf("未知消息类型: %d\n", messageType)
return
}
}
}
func NewServer() *gin.Engine {
gin.SetMode(gin.DebugMode) // 设置运行模式
gin.DisableConsoleColor() // 禁用控制台输出的颜色
router := gin.Default()
return router
}
func main() {
// 创建Gin应用
app := NewServer()
// 注册WebSocket路由
app.GET("/ws", WebSocketHandler)
// 启动应用
err := app.Run("127.0.0.1:8080")
if err != nil {
panic(err)
}
}
客户端
写个了命令行客户端用于连接websocket服务端,接收键盘输入,然后发送到服务端。使用flag解析命令行参数用于配置服务端连接。
package main
import (
"flag"
"fmt"
"log"
"net/http"
"net/url"
"os"
"os/signal"
"syscall"
"time"
"github.com/gorilla/websocket"
)
var (
Addr string
Path string
Token string
)
func init() {
flag.StringVar(&Addr, "addr", "localhost:8080", "WebSocket 服务器地址")
flag.StringVar(&Path, "path", "/ws", "WebSocket接口路由")
flag.StringVar(&Token, "token", "123456", "连接 WebSocket 服务器的令牌")
flag.Parse()
}
func main() {
header := make(http.Header)
header.Set("token", Token)
u := url.URL{Scheme: "ws", Host: Addr, Path: "/ws"}
conn, _, err := websocket.DefaultDialer.Dial(u.String(), header)
if err != nil {
log.Fatalf("连接 WebSocket 服务器失败:%v", err)
return
}
defer conn.Close()
// 创建channel用于监听操作系统的中断信号
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
response := make(chan string, 8)
defer close(response)
// 启动一个 goroutine 用于接收 WebSocket 服务器的响应
go func(resp chan string) {
for {
_, message, err := conn.ReadMessage()
if err != nil {
log.Printf("server> ERROR! %v\n", err)
return
}
resp <- string(message)
}
}(response)
// 读取用户的键盘输入,并发送到 WebSocket 服务器
for {
select {
case <-interrupt: // 等待中断信号
log.Println("收到中断信号,关闭 WebSocket 连接 ...")
err := conn.WriteMessage(
websocket.CloseMessage,
websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
if err != nil {
log.Printf("发送关闭消息失败:%v\n", err)
}
<-interrupt // 关闭websocket连接之前, 确保已经发送到服务端的消息能够被确认和处理
return
default:
var input string
fmt.Printf("%s client> ", time.Now().Format("2006-01-02 15:04:05"))
fmt.Scanln(&input)
if input == "exit" {
log.Println("用户输入 exit, 关闭 WebSocket 连接 ...")
err := conn.WriteMessage(
websocket.CloseMessage,
websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
if err != nil {
log.Printf("发送关闭消息失败:%v", err)
return
}
return
}
if len(input) == 0 {
log.Println("输入消息为空")
continue
}
err := conn.WriteMessage(websocket.TextMessage, []byte(input))
if err != nil {
log.Printf("发送消息失败:%v", err)
continue
}
// 阻塞等待服务端响应
resp := <-response
log.Printf("server> %s\n", resp)
}
}
}
参考
[golang]gin框架接收websocket通信的更多相关文章
- golang(gin框架),基于RESTFUL的跨语言远程通信尝试
golang(gin框架),基于RESTFUL的跨语言远程通信尝试 背景: 在今年的项目实训过程中,遇到了这样的问题: 企业老师讲课实用的技术栈是Java springboot. 实训实际给我们讲课以 ...
- 前端程序员学习 Golang gin 框架实战笔记之一开始玩 gin
原文链接 我是一名五六年经验的前端程序员,现在准备学习一下 Golang 的后端框架 gin. 以下是我的学习实战经验,记录下来,供大家参考. https://github.com/gin-gonic ...
- golang Gin framework with websocket
概述 golang websocket 库 示例 后端 前端 结论 概述 对于 golang 的 web 开发, 之前写过 2 篇 blog, 分别介绍了: 在 Gin 框架下, 各类 http AP ...
- golang gin框架中实现一个简单的不是特别精确的秒级限流器
起因 看了两篇关于golang中限流器的帖子: Gin 开发实践:如何实现限流中间件 常用限流策略--漏桶与令牌桶介绍 我照着用,居然没效果-- 时间有限没有深究.这实在是一个很简单的功能,我的需求是 ...
- Golang gin框架学习
今天开始学习gin框架,在Github上找的示例的go-gin-example, 进度 日期 进展 疑惑 进展 1.30 下拉代码,初步了解gin的介绍.搭建 .mod文件 module原理.使用方法 ...
- golang gin框架中实现大文件的流式上传
一般来说,通过c.Request.FormFile()获取文件的时候,所有内容都全部读到了内存.如果是个巨大的文件,则可能内存会爆掉:且,有的时候我们需要一边上传一边处理. 以下的代码实现了大文件流式 ...
- [Golang] Gin框架学习笔记
0x0 Gin简介 1.Gin 是什么? Gin 是一个用 Go (Golang) 编写的 HTTP web 框架. 它是一个类似于 martini 但拥有更好性能的 API 框架, 由于 httpr ...
- golang gin框架 使用swagger生成api文档
github地址:https://github.com/swaggo/gin-swagger 1.下载swag $ go get -u github.com/swaggo/swag/cmd/swag ...
- golang gin框架中实现"Transfer-Encoding: chunked"方式的分块发送数据到浏览器端
参考了这篇帖子: https://golangtc.com/t/570b403eb09ecc66b90002d9 golang web如何发送小包的chunked数据 以下是代码: r.GET(&qu ...
- golang gin框架设置静态目录
router := gin.Default() 第一个参数是api 第二个静态问价的文件夹相对目录 router.StaticFS("/data", http.Dir(" ...
随机推荐
- 分布式搜索引擎Elasticsearch基础入门学习
一.Elasticsearch介绍 Elasticsearch介绍 Elasticsearh 是 elastic.co 公司开发的分布式搜索引擎. Elasticsearch(简称ES)是一个开源的分 ...
- String、StringBuilder、StringBuffer使用场景
String:加了final修饰,长度不可变,每次修改会创建新String:操作少量数据或者不需要操作数据时使用. StringBuilder:长度可变,线程不安全:在需要频繁操作数据且不需要考虑线程 ...
- 「Vue系列」之Vue2实现当前组件重新加载
遇到问题的场景:需要把当前组件完全还原成初始化状态,不要页面全部刷新例如:重置按钮,只刷新当前加载组件其他办法:使用vue-router重新定向到当前页面,页面不刷新使用window-reload() ...
- vue工程内下载路由
一.路由Router Vue Router 是Vue.js官方的路由管理器.它和Vue.js的核心深度集成,加速构建单页面应用.包含功能有: 1 嵌套的路由/视图表 2 模块化的.基于组件的路由配置 ...
- Deferred Components-实现Flutter运行时动态下发Dart代码 | 京东云技术团队
导读 Deferred Components,官方实现的Flutter代码动态下发的方案.本文主要介绍官方方案的实现细节,探索在国内环境下使用Deferred Components,并且实现了最小验证 ...
- AcWing 278. 数字组合
给定 N 个正整数 A1,A2,-,AN,从中选出若干个数,使它们的和为 M,求有多少种选择方案. 输入格式 第一行包含两个整数 N 和 M. 第二行包含 N 个整数,表示 A1,A2,-,AN. 输 ...
- 为什么 HashMap 会死循环?
HashMap 死循环发生在 JDK 1.8 之前的版本中,它是指在并发环境下,因为多个线程同时进行 put 操作,导致链表形成环形数据结构,一旦形成环形数据结构,在 get(key) 的时候就会产生 ...
- OpenOffice4.1.6 linux安装/卸载教程
以下是centos的安装方法 1.先安装并配置好jdk 2.拷贝 把Apache_OpenOffice_4.1.6_Linux_x86-64_install-rpm_zh-CN.tar.gz拷贝到自己 ...
- 2023-06-13:统计高并发网站每个网页每天的 UV 数据,结合Redis你会如何实现?
2023-06-13:统计高并发网站每个网页每天的 UV 数据,结合Redis你会如何实现? 答案2023-06-13: 选用方案:HyperLogLog 如果统计 PV (页面浏览量)那非常好办,可 ...
- 如何让ChatGPT高效的理解你的Prompt
1.概述 ChatGPT是由 OpenAI 开发的一种强大的语言模型,它在许多自然语言处理任务中展现出了惊人的能力.而其中一个关键的技术概念就是 "Prompt".本文将深入探讨 ...