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"))
    }
    }
    }
  • 相关阅读:
    联合主键SQL 联合索引
    SQL 对decimal类型转换为int类型
    SQL获取当前时间月份为两位数
    SQL 对结果集进行分组排序过滤重复数据 ROW_NUMBER
    SQL自动流水号函数
    SQL 索引创建
    .Net三层架构
    2016年你应该学习的语言和框架(转)
    MongoDB学习笔记(转)
    干货分享:让你分分钟学会 javascript 闭包(转)
  • 原文地址:https://www.cnblogs.com/ashion89/p/14177610.html
Copyright © 2011-2022 走看看