zoukankan      html  css  js  c++  java
  • go工具方法-websocket

    package websocket

    import (
    "fmt"
    "github.com/gin-gonic/gin"
    "github.com/gorilla/websocket"
    "github.com/unknwon/com"
    "net/http"
    "sync"
    "time"
    )
    //启动websocket
    func init() {
    go broadcaster()
    }

    type Client struct {
    conn *websocket.Conn // 用户websocket连接
    user_id int // 用于区分用户的socket
    }

    type Message struct {
    Content string `json:"content"` //消息内容,可以是对象
    }

    var clients = sync.Map{} // 用户组映射 user -client
    var MesChannel = make(chan Message, 500) // 消息通道

    var join = make(chan Client, 100) // 用户加入通道
    var leave = make(chan Client, 100) // 用户退出通道

    //websocket连接方法 u_id代表用户标识
    func WS(c *gin.Context) {

    user_id := com.StrTo(c.Query("u_id")).MustInt()
    if user_id == 0 {
    c.Redirect(302, "/")
    return
    }
    // 检验http头中upgrader属性,若为websocket,则将http协议升级为websocket协议
    conn, err := websocket.Upgrade(c.Writer, c.Request, nil, 1024, 1024)
    if _, ok := err.(websocket.HandshakeError); ok {
    http.Error(c.Writer, "Not a websocket handshake", 400)
    return
    } else if err != nil {
    fmt.Println("Cannot setup WebSocket connection:", err)
    return
    }

    client := Client{
    conn: conn,
    user_id: user_id,
    }

    // 如果用户列表中没有该用户
    if _, ok := clients.Load(user_id); !ok {
    clients.Store(user_id,client) // 将用户加入map
    join <- client
    }

    // 当函数返回时,将该用户加入退出通道,并断开用户连接
    defer func() {
    clients.Delete(client.user_id)
    leave <- client //离开
    client.conn.Close()
    }()

    for {
    // 读取消息。如果连接断开,则会返回错误
    _, msgStr, err := client.conn.ReadMessage()

    // 如果返回错误,就退出循环
    if err != nil {
    break
    }

    if err := client.conn.WriteMessage(websocket.TextMessage, msgStr); err != nil {
    fmt.Println("heartcheck userid:", client.user_id)
    break
    }

    // 如果没有错误,则把用户发送的信息放入message通道中,
    msg := Message{
    Content: string(msgStr),
    }
    MesChannel <- msg
    }
    }

    /*前端send的消息格式,可自行修改:
    {
    content:"new"
    }
    */
    func broadcaster() {
    for {

    select {
    // 消息通道中有消息则执行,否则堵塞
    case msg := <-MesChannel:
    content := msg.Content
    //广播给在线的用户
    clients.Range(func(key, value interface{}) bool {
    if client, ok := clients.Load(key); ok {
    if c,ok:=client.(Client);ok{
    if err := c.conn.WriteMessage(websocket.TextMessage, []byte(content)); err != nil {
    fmt.Println("push fail userid:", key)
    }else {
    fmt.Println("push success userid:", key)
    }
    }
    }
    return true
    })

    // 有用户加入
    case client := <-join:
    fmt.Println("userid:", client.user_id, "---join,time:", time.Now().Format("2006-01-02 15:04:05"))
    // 有用户退出
    case client := <-leave:
    fmt.Println("userid:", client.user_id, "---leave,time:", time.Now().Format("2006-01-02 15:04:05"))
    }
    }
    }
  • 相关阅读:
    将Nginx添加到windows服务中
    springboot使用redis管理session
    GIT常用命令
    阻止360、谷歌浏览器表单自动填充
    谈谈对Spring IOC的理解
    同一个Nginx服务器同一端口配置多个代理服务
    LeetCode 653. Two Sum IV
    109. Convert Sorted List to Binary Search Tree(根据有序链表构造平衡的二叉查找树)
    108. Convert Sorted Array to Binary Search Tree(从有序数组中构造平衡的BST)
    LeetCode 236. Lowest Common Ancestor of a Binary Tree(二叉树求两点LCA)
  • 原文地址:https://www.cnblogs.com/ashion89/p/14177610.html
Copyright © 2011-2022 走看看