前言

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通信的更多相关文章

  1. golang(gin框架),基于RESTFUL的跨语言远程通信尝试

    golang(gin框架),基于RESTFUL的跨语言远程通信尝试 背景: 在今年的项目实训过程中,遇到了这样的问题: 企业老师讲课实用的技术栈是Java springboot. 实训实际给我们讲课以 ...

  2. 前端程序员学习 Golang gin 框架实战笔记之一开始玩 gin

    原文链接 我是一名五六年经验的前端程序员,现在准备学习一下 Golang 的后端框架 gin. 以下是我的学习实战经验,记录下来,供大家参考. https://github.com/gin-gonic ...

  3. golang Gin framework with websocket

    概述 golang websocket 库 示例 后端 前端 结论 概述 对于 golang 的 web 开发, 之前写过 2 篇 blog, 分别介绍了: 在 Gin 框架下, 各类 http AP ...

  4. golang gin框架中实现一个简单的不是特别精确的秒级限流器

    起因 看了两篇关于golang中限流器的帖子: Gin 开发实践:如何实现限流中间件 常用限流策略--漏桶与令牌桶介绍 我照着用,居然没效果-- 时间有限没有深究.这实在是一个很简单的功能,我的需求是 ...

  5. Golang gin框架学习

    今天开始学习gin框架,在Github上找的示例的go-gin-example, 进度 日期 进展 疑惑 进展 1.30 下拉代码,初步了解gin的介绍.搭建 .mod文件 module原理.使用方法 ...

  6. golang gin框架中实现大文件的流式上传

    一般来说,通过c.Request.FormFile()获取文件的时候,所有内容都全部读到了内存.如果是个巨大的文件,则可能内存会爆掉:且,有的时候我们需要一边上传一边处理. 以下的代码实现了大文件流式 ...

  7. [Golang] Gin框架学习笔记

    0x0 Gin简介 1.Gin 是什么? Gin 是一个用 Go (Golang) 编写的 HTTP web 框架. 它是一个类似于 martini 但拥有更好性能的 API 框架, 由于 httpr ...

  8. golang gin框架 使用swagger生成api文档

    github地址:https://github.com/swaggo/gin-swagger 1.下载swag $ go get -u github.com/swaggo/swag/cmd/swag ...

  9. golang gin框架中实现"Transfer-Encoding: chunked"方式的分块发送数据到浏览器端

    参考了这篇帖子: https://golangtc.com/t/570b403eb09ecc66b90002d9 golang web如何发送小包的chunked数据 以下是代码: r.GET(&qu ...

  10. golang gin框架设置静态目录

    router := gin.Default() 第一个参数是api 第二个静态问价的文件夹相对目录 router.StaticFS("/data", http.Dir(" ...

随机推荐

  1. 试用「ChatGPT」几周之后

    冷静下来,不吹不黑. 01 最近半年,互联网一款现象级的应用诞生:「ChatGPT」: 其火爆的程度,不输前面的羊了个羊: 最初了解到ChatGPT还是春节的时候,但那时网上的测评还没引起足够的好奇心 ...

  2. 在 CentOS 上搭建 Mumble 服务器

    Mumble 服务器搭建 前言 Mumble 是一个开源.低延迟.高质量的语音通话平台.可以在多个平台搭建,并且有多个开源的客户端(Windows.Linux.Android.MacOS).这是 官网 ...

  3. Java JDK1.8环境变量配置

    Java JDK1.8.0_152下载地址:https://pan.baidu.com/s/1BRB2MRETPdWVL-IN2FRTEw   提取码:63jb 下载好后傻瓜式一键Next下载就好,默 ...

  4. tkinter的Entry设置为不可编辑状态

    前 首先我们知道,tkinter中有许许多多的控件,其中使用频繁的控件之一就是Entry(输入框),那么怎么设置它为不可编辑状态呢? state选项 一般我们在写Entry的时候只传入了一个maste ...

  5. 献给转java的c#和java程序员的数据库orm框架

    献给转java的c#和java程序员的数据库orm框架 一个好的程序员不应被语言所束缚,正如我现在开源java的orm框架一样,如果您是一位转java的c#程序员,那么这个框架可以带给你起码没有那么差 ...

  6. vst实例(2) 创建VST

    前面我们知道,创建一个虚拟树,应该首先告知VST节点数据的大小(即nodedatasize),其实在创建树结构时,这一点并不是必须的,而是如果你需要让VST的每一个节点能指向一定的数据,从而在执行树的 ...

  7. Hugging News #0602: Transformers Agents 介绍、大语言模型排行榜发布!

    每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新.社区活动.学习资源和内容更新.开源库和模型更新等,我们将其称之为「Hugging Ne ...

  8. Python 包安装和 postgresql 的一些问题

    今天安装 hgvs 这个 python 包的时候,遇到几个比较有代表性的问题,记录分享一下. hgvs is a Python package to parse, format, validate, ...

  9. ChatGLM 拉取清华git项目

    windows使用nvdia显卡运行ChatGLM 1. 安装nvidia显卡驱动 https://developer.nvidia.com/cuda-11-8-0-download-archive? ...

  10. Python3.9安装

    一.安装python3.9 链接:https://pan.baidu.com/s/1mDkgKt2KSoMrKVxesb76Pg?pwd=ma4n 提取码:ma4n --来自百度网盘超级会员V4的分享 ...