0%

go搭建websocket服务

go搭建websocket服务

之前整理go包管理工具的时候用的是自己做websocket服务的半成品代码,今天把做websocket服务的代码完善下

所用包

go官方是没有websocket的包的,这里笔者用的是第三方开发的一个包 gorilla/websocket,代码是笔者在官方的demo的基础上更改的

实现功能

笔者目前次项目简单的实现了 前端绑定后,给服务端发消息,服务的把收到的消息直接再发送给前端, 这个功能是官方demo里就有的,笔者主要实现的是,添加了个接口 后端接受GET请求后, 主动发消息给所有绑定的前端服务
接口:

  • send 接受msg参数 把msg发给所有绑定的socket客户端
  • echo 默认绑定事件
  • home 页面入口
    代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    package main

    import (
    "flag"
    "html/template"
    "log"
    "net/http"
    "github.com/gorilla/websocket"
    )

    /*
    type room struct{
    roomId int64
    users sync.Map
    }*/

    var addr = flag.String("addr", "localhost:8080", "http service address")

    var upgrader = websocket.Upgrader{} // use default options

    //var c *websocket.Conn
    //定义socket 集合 所有socket共用一个集合 扩展下 定义组 每个组 socket消息互通
    var room map[int]*websocket.Conn
    var i int = 0

    func send(w http.ResponseWriter, r *http.Request) {
    query := r.URL.Query()
    msg := query.Get("msg")
    for clt := range room{
    err := room[clt].WriteMessage(websocket.TextMessage, []byte(msg))
    if err != nil {
    delete(room, clt)
    log.Println("write:", err)
    log.Println("delete:", clt)
    }
    }
    w.Write([]byte("send"))
    }
    func echo(w http.ResponseWriter, r *http.Request) {
    //var err error
    c, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
    log.Print("upgrade:", err)
    return
    }
    room[i] = c
    i++
    defer c.Close()
    for {
    mt, message, err := c.ReadMessage()
    if err != nil {
    log.Println("read:", err)
    break
    }
    log.Printf("recv: %s", message)
    err = c.WriteMessage(mt, message)
    if err != nil {
    log.Println("write:", err)
    break
    }
    }
    }

    func home(w http.ResponseWriter, r *http.Request) {
    homeTemplate.Execute(w, "ws://"+r.Host+"/echo")
    }

    func main() {
    room = make(map[int]*websocket.Conn)
    flag.Parse()
    log.SetFlags(0)
    http.HandleFunc("/echo", echo)
    http.HandleFunc("/", home)
    http.HandleFunc("/send", send)
    log.Fatal(http.ListenAndServe(*addr, nil))
    }

    var homeTemplate = template.Must(template.New("").Parse(`
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script>
    window.addEventListener("load", function(evt) {
    var output = document.getElementById("output");
    var input = document.getElementById("input");
    var ws;
    var print = function(message) {
    var d = document.createElement("div");
    d.textContent = message;
    output.appendChild(d);
    output.scroll(0, output.scrollHeight);
    };
    document.getElementById("open").onclick = function(evt) {
    if (ws) {
    return false;
    }
    ws = new WebSocket("{{.}}");
    ws.onopen = function(evt) {
    print("OPEN");
    }
    ws.onclose = function(evt) {
    print("CLOSE");
    ws = null;
    }
    ws.onmessage = function(evt) {
    print("RESPONSE: " + evt.data);
    }
    ws.onerror = function(evt) {
    print("ERROR: " + evt.data);
    }
    return false;
    };
    document.getElementById("send").onclick = function(evt) {
    if (!ws) {
    return false;
    }
    print("SEND: " + input.value);
    ws.send(input.value);
    return false;
    };
    document.getElementById("close").onclick = function(evt) {
    if (!ws) {
    return false;
    }
    ws.close();
    return false;
    };
    });
    </script>
    </head>
    <body>
    <table>
    <tr><td valign="top" width="50%">
    <p>Click "Open" to create a connection to the server,
    "Send" to send a message to the server and "Close" to close the connection.
    You can change the message and send multiple times.
    <p>
    <form>
    <button id="open">Open</button>
    <button id="close">Close</button>
    <p><input id="input" type="text" value="Hello world!">
    <button id="send">Send</button>
    </form>
    </td><td valign="top" width="50%">
    <div id="output" style="max-height: 70vh;overflow-y: scroll;"></div>
    </td></tr></table>
    </body>
    </html>
    `))