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"))
    }
    }
    }
  • 相关阅读:
    支持向量机SVM知识点概括
    决策树知识点概括
    HDU 3081 Marriage Match II
    HDU 3572 Task Schedule
    HDU 4888 Redraw Beautiful Drawings
    Poj 2728 Desert King
    HDU 3926 Hand in Hand
    HDU 1598 find the most comfortable road
    HDU 4393 Throw nails
    POJ 1486 Sorting Slides
  • 原文地址:https://www.cnblogs.com/ashion89/p/14177610.html
Copyright © 2011-2022 走看看