golang Gin实现websocket

golang使用 Gin实现 websocket,这里笔者重新搭建一个项目

1、创建项目安装依赖

项目名为 go-gin-websocket

在指定文件夹下,新建项目文件夹 go-gin-websocket

d90ea17676bd4ff68ddeb5ecd43845f5.png

进入项目文件夹,打开cmd窗口,在项目(go-gin-websocket)文件夹路径下,执行初始化命令 go mod init go-gin-websocket

go mod init go-gin-websocket

ef282acdb84846dbbaf3c2159feec61c.png

安装依赖

安装gin

go get -u github.com/gin-gonic/gin

 安装websocket

go get github.com/gorilla/websocket

ce9b1f9416f24320a90e01cf7ac8aef2.png

2、搭建项目

在项目目录下新建controller、static、templates、ws文件夹,分别用来存放controller代码、静态文件、页面、websocket代码

05f4bfb81ae94370aa0c7f51b6194ab1.png

在templates目录下新建 index.html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
hello
<script>
    var webSocket;
    try {
        webSocket = new WebSocket('ws://127.0.0.1:8080/ws?id=abc123456789');
    }catch (e) {
        console.log(e)
    }

    webSocket.onerror = function(event) {}

    //与WebSocket建立连接
    webSocket.onopen = function(event) {
        console.log('建立连接')
        console.log(JSON.stringify(event))
        var msg = "身无彩凤双飞翼,心有灵犀一点通"
        //发送消息
        webSocket.send(msg);
    };
    //接收服务端发送的消息
    webSocket.onmessage=function (m) {
        console.log(m)
        console.log(m.data)
    }
</script>
</body>
</html>

在controller目录下新建 page_controller.go

package controller

import "github.com/gin-gonic/gin"

func Index(c *gin.Context) {
	c.HTML(200, "index.html", nil)
}

在ws目录下新建 websocket.go

package ws

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
)

func InitWebSocket(c *gin.Context) {
	var upgrader = websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
		CheckOrigin: func(r *http.Request) bool {
			log.Println("升级协议", r.Header["User-Agent"])
			return true
		},
	}

	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Println(err)
		return
	}
	defer conn.Close()
	userId := c.Query("id")
	log.Println("用户id:", userId)

	for {
		mt, message, err := conn.ReadMessage()

		log.Println("获取客户端发送的消息:" + string(message))
		fmt.Println(mt)
		if err != nil {
			log.Println(err)
			break
		}

		var msg = "春风得意马蹄疾,一日看尽长安花"
		err2 := conn.WriteMessage(websocket.TextMessage, []byte(msg))
		if err2 != nil {
			log.Println("write:", err2)
			break
		}
	}

}

在项目根目录下新建 main.go

243f3a9eeafa4deda10a5bc7c77d3da6.png

main.go内容

package main

import (
	"github.com/gin-gonic/gin"
	"go-gin-websocket/controller"
	"go-gin-websocket/ws"
)

func main() {
	e := gin.Default()
	//html页面位置
	e.LoadHTMLGlob("templates/*")
	//静态文件位置
	e.Static("/static", "./static")

	e.GET("/", controller.Index)
	e.GET("/ws", ws.InitWebSocket)

	e.Run("0.0.0.0:8080")
}

3、运行测试

浏览器请求 http://localhost:8080/

1da3a379a25041bfb3861d916c946168.gif

4、添加session

添加session用来存储在线用户

这里使用一个map用来保存,key是用户id,value是websocket连接,再加一个读写锁保证线程安全

package ws

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
	"sync"
)

var connects = make(map[string]*websocket.Conn)
var lock sync.RWMutex

func addSession(id string, conn *websocket.Conn) {
	lock.Lock()
	connects[id] = conn
	defer lock.Unlock()
}
func getSession(id string) *websocket.Conn {
	lock.RLock()
	defer lock.RUnlock()
	return connects[id]
}
func removeSession(id string) {
	lock.Lock()
	delete(connects, id)
	defer lock.Unlock()
}

func InitWebSocket(c *gin.Context) {
	var upgrader = websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
		CheckOrigin: func(r *http.Request) bool {
			log.Println("升级协议", r.Header["User-Agent"])
			return true
		},
	}

	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Println(err)
		return
	}
	defer conn.Close()
	userId := c.Query("id")
	log.Println("用户id:", userId)

	//添加session
	addSession(userId, conn)

	for {
		mt, message, err := conn.ReadMessage()

		log.Println("获取客户端发送的消息:" + string(message))
		fmt.Println(mt)
		if err != nil {
			log.Println(err)
			break
		}

		var msg = "春风得意马蹄疾,一日看尽长安花"
		err2 := conn.WriteMessage(websocket.TextMessage, []byte(msg))
		if err2 != nil {
			log.Println("write:", err2)
			break
		}
	}

}

至此完

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Golang中的Gin框架提供了一种简单而强大的方法来构建Web应用程序。与此同时,Golang标准库中的"net/http"包提供了构建WebSocket服务器和客户端的功能。 首先,我们来看一下如何使用GinWebSocket构建WebSocket服务器。首先,需要导入相关的包: ```go import ( "github.com/gin-gonic/gin" "github.com/gorilla/websocket" ) ``` 接下来,在Gin中创建一个WebSocket处理函数: ```go func WebSocketHandler(c *gin.Context) { upgrader := websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, } conn, err := upgrader.Upgrade(c.Writer, c.Request, nil) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } for { messageType, message, err := conn.ReadMessage() if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } err = conn.WriteMessage(messageType, message) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } } } ``` 上面的代码创建了一个基本的WebSocket处理函数。它使用WebSocket标准库中的Upgrader结构来处理升级连接并创建一个WebSocket连接。 然后,我们需要在Gin中设置路由来处理WebSocket请求: ```go router := gin.Default() router.GET("/ws", WebSocketHandler) ``` 以上代码将在根路径下创建一个WebSocket处理函数。 接下来,我们来看一下如何使用GolangGin构建WebSocket客户端。首先,我们需要导入所需的包: ```go import ( "github.com/gorilla/websocket" "net/http" ) ``` 然后,我们可以使用以下代码来创建一个WebSocket客户端: ```go func main() { c, _, err := websocket.DefaultDialer.Dial("ws://localhost:8080/ws", 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 <-ticker.C: err := c.WriteMessage(websocket.TextMessage, []byte("Hello, Server!")) if err != nil { log.Println("write:", err) return } } } } ``` 上面的代码创建了一个WebSocket客户端,它使用WebSocket标准库中的`DefaultDialer`结构来建立WebSocket连接。 以上就是使用Golang GinWebSocket构建WebSocket客户端和服务器的简单示例。这些代码可以帮助我们使用GinGolang的标准库来构建强大的Web应用程序,并处理WebSocket通信。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟世君子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值