zoukankan      html  css  js  c++  java
  • golang 实现并发的websocket

    公司要求使用golang做识别系统的web后端,我采用gin框架开发,其中部分功能使用了websocket实现前后端的实时消息推送刷新。

    记录一下golang中使用channel和锁将websocket封装成为可并发读写的websocket:

    package cws
    
    import (
    	"errors"
    	"github.com/gorilla/websocket"
    	"sync"
    )
    
    //封装websocket并发读写操作
    
    type Connection struct {
    	WsConn    *websocket.Conn
    	InChan    chan []byte
    	OutChan   chan models.BayDataS
    	CloseChan chan byte
    	Mutex     sync.Mutex
    	IsClosed  bool
    }
    
    func InitConnection(wsConn *websocket.Conn) (conn *Connection, err error) {
    	conn = &Connection{
    		WsConn:    wsConn,
    		InChan:    make(chan []byte, 1000),
    		OutChan:   make(chan []byte, 1000),
    		CloseChan: make(chan byte, 1),
    	}
    	//读协程
    	go conn.ReadLoop()
    	//写协程
    	go conn.WriteLoop()
    	return
    }
    
    func (conn *Connection) ReadMess() (data []byte, err error) {
    	select {
    	case data = <-conn.InChan:
    	case <-conn.CloseChan:
    		err = errors.New("connection is closed")
    	}
    	return
    }
    
    func (conn *Connection) WriteMes(data []byte) (err error) {
    	select {
    	case conn.OutChan <- data:
    	case <-conn.CloseChan:
    		err = errors.New("connection is closed")
    	}
    	return
    }
    
    func (conn *Connection) Close() {
    	conn.Close() //本身线程安全,可重入
    	//加锁,只能执行一次
    	conn.Mutex.Lock()
    	if !conn.IsClosed {
    		close(conn.CloseChan)
    		conn.IsClosed = true
    	}
    }
    
    //具体实现读消息
    func (conn *Connection) ReadLoop() {
    	var (
    		data []byte
    		err  error
    	)
    	for {
    		if _, data, err = conn.WsConn.ReadMessage(); err != nil {
    			goto ERR
    		}
    		select {
    		case conn.InChan <- data:
    		case <-conn.CloseChan:
    			goto ERR
    		}
    	}
    ERR:
    	conn.Close()
    }
    
    //具体实现写消息
    func (conn *Connection) WriteLoop() {
    	var (
    		data models.BayDataS
    		err  error
    	)
    	for {
    		select {
    		case data = <-conn.OutChan:
    		case <-conn.CloseChan:
    			goto ERR
    		}
    		if err = conn.WsConn.WriteMessage(websocket.TextMessage, data); err != nil {
    			goto ERR
    		}
    	}
    ERR:
    	conn.Close()
    }
    

    当然websocket支持发送和接收的消息多种,像我的话常用的是Json 如:

    conn.WsConn.WriteJSON(data) //data可以是struct,map等
  • 相关阅读:
    AutoCAD LISP矩形窗格绘制
    AutoCAD VBA多重延伸
    2011年3月24日星期四
    AutoCAD VBA对齐对象
    AutoCAD VBA根据对象缩放
    AutoCAD LISP绘制多个等半径圆相切
    AutoCAD LISP利用一顶点和三边长绘制三角形
    AutoCAD VBA对象的组合和拆散
    AutoCAD LISP修改已存在圆半径
    AutoCAD VBA基于对象的分层
  • 原文地址:https://www.cnblogs.com/cfc-blog/p/13160857.html
Copyright © 2011-2022 走看看