首页 > 其他分享 >gin webscoket

gin webscoket

时间:2022-11-22 21:38:12浏览次数:42  
标签:websocket type make chan json Client gin webscoket

package main

import (
	"encoding/json"
	"github.com/gin-gonic/gin"
	uuid "github.com/satori/go.uuid"
	"net/http"

	"github.com/gorilla/websocket"
)

// ClientManager is a websocket manager
type ClientManager struct {
	Clients    map[*Client]bool
	Broadcast  chan []byte
	Register   chan *Client
	Unregister chan *Client
}

// Client is a websocket client
type Client struct {
	ID     string
	Socket *websocket.Conn
	Send   chan []byte
}

// Message is an object for websocket message which is mapped to json type
type Message struct {
	Sender    string `json:"sender,omitempty"`
	Recipient string `json:"recipient,omitempty"`
	Content   string `json:"content,omitempty"`
}

// Manager define a ws server manager
var Manager = ClientManager{
	Broadcast:  make(chan []byte),
	Register:   make(chan *Client),
	Unregister: make(chan *Client),
	Clients:    make(map[*Client]bool),
}

// Start is to start a ws server
func (manager *ClientManager) Start() {
	for {
		select {
		case conn := <-manager.Register:
			manager.Clients[conn] = true
			jsonMessage, _ := json.Marshal(&Message{Content: "/A new socket has connected."})
			manager.Send(jsonMessage, conn)
		case conn := <-manager.Unregister:
			if _, ok := manager.Clients[conn]; ok {
				close(conn.Send)
				delete(manager.Clients, conn)
				jsonMessage, _ := json.Marshal(&Message{Content: "/A socket has disconnected."})
				manager.Send(jsonMessage, conn)
			}
		case message := <-manager.Broadcast:
			for conn := range manager.Clients {
				select {
				case conn.Send <- message:
				default:
					close(conn.Send)
					delete(manager.Clients, conn)
				}
			}
		}
	}
}

// Send is to send ws message to ws client
func (manager *ClientManager) Send(message []byte, ignore *Client) {
	for conn := range manager.Clients {
		if conn != ignore {
			conn.Send <- message
		}
	}
}

func (c *Client) Read() {
	defer func() {
		Manager.Unregister <- c
		c.Socket.Close()
	}()

	for {
		_, message, err := c.Socket.ReadMessage()
		if err != nil {
			Manager.Unregister <- c
			c.Socket.Close()
			break
		}
		jsonMessage, _ := json.Marshal(&Message{Sender: c.ID, Content: string(message)})
		Manager.Broadcast <- jsonMessage
	}
}

func (c *Client) Write() {
	defer func() {
		c.Socket.Close()
	}()

	for {
		select {
		case message, ok := <-c.Send:
			if !ok {
				c.Socket.WriteMessage(websocket.CloseMessage, []byte{})
				return
			}

			c.Socket.WriteMessage(websocket.TextMessage, message)
		}
	}
}

func main() {
	// 创建一个默认的路由引擎
	r := gin.Default()
	// 配置路由
	r.GET("/", func(c *gin.Context) {
		// change the reqest to websocket model
		conn, error := (&websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}).Upgrade(c.Writer, c.Request, nil)
		if error != nil {
			http.NotFound(c.Writer, c.Request)
			return
		}
		// websocket connect
		client := &Client{ID: uuid.NewV4().String(), Socket: conn, Send: make(chan []byte)}

		Manager.Register <- client

		go client.Read()
		go client.Write()
	})
	// 启动 HTTP 服务,默认在 0.0.0.0:8080 启动服务
	r.Run()
}

标签:websocket,type,make,chan,json,Client,gin,webscoket
From: https://www.cnblogs.com/wtil/p/16916496.html

相关文章

  • CodeForces - 320E Kalila and Dimna in the Logging Industry
    题意:你有要拿一把锯子砍树。锯子有有电和没电两个状态,只有在有电的时候才能工作,每次工作都可以砍1单位高度的树,然后就会没电。没电后要充电才能工作。充电有代价,代价为,当前......
  • Nginx 使用ngx_http_map_module模块的map指令遇到的常见问题。
    ngx_http_map_module请先看参阅的NginxMap指令文档后吧。这里的说明比较简略。基本使用Demohttp{map"beijing"$Name{default"中国";"beijing""北......
  • Nginx underscores_in_headers和ignore_invalid_headers的作用,自我理解的作用。
    underscores_in_headers直达underscores_in_headers启用或禁用在客户端请求标头字段中使用下划线。当禁用下划线时,名称包含下划线的请求标头字段将被标记为无效并受制于......
  • Linux C编程 使用相对路径加载动态库-rpath和$ORIGIN
    商业程序如何加载自己的so使用LD_LIBRARY_PATH的缺点是要实现设置LD_LIBRARY_PATH。不够自动化。那么大型的商业程序是如何加载自己的so呢。这里以QtCreator为例。QtC......
  • Nginx if,set指令所在模块位置
    ngx_http_rewrite_module模块包含if,set,rewrite,return等指令ngx可用的环境变量直达文档ngx下通过http_XXX引用header项......
  • 134-腾讯云服务器装Tengine
    第1步:yuminstallgccgcc-c++autoconfautomake出现类似如下错误:Couldnotresolvehost:mirrors.tencentyun.com;Unknownerror百度结果说:我们需要把DNS恢复为......
  • Nginx之location匹配规则
    什么是location?nginx就是通过拦截到的请求去对配置好的location块(locationblock)进行请求代理的。被代理的URL去对location后边的字符串(或正则)根据一定的规则进行匹配,然后......
  • nginx之location块配置
    匹配location块和server块一样,Nginx有一套既定的规则来决定server中哪一块location来处理请求location块语法在我们了解nginx如何区分哪个模块处理哪些请求之前,我们先了解......
  • Gradle7.0引入plugin
    在gradle7.0引入使用plugin已经发生了更改.举例使用7.0之前1.引入方式是在project的build.gradle中这样配置buildscript{ repositories{ maven{url'xxxx'} ......
  • nginx常见问题
    前言本文记载一些nginx常见问题1.connect()fail转发的服务挂了,确保主服务正常运行。可以使用lsof-i:端口号确定被转接的服务的状态2.nginx50X的错误日志去哪看,配置......