当前位置: 代码迷 >> 综合 >> Go实战--golang中使用WebSocket实时聊天室 gorilla/websocket nkovacs/go-s
  详细解决方案

Go实战--golang中使用WebSocket实时聊天室 gorilla/websocket nkovacs/go-s

热度:30   发布时间:2024-01-21 07:49:14.0
                       

生命不止,继续 go go go!!!

其实,早就应该跟大家分享golang中关于websocket的使用,但是一直不知道从何入手,也不能够很清晰的描述出来。

今天就浅尝辄止,通过第三方库实现websocket。

WebSocket

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。
WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范。

WebSocket协议支持(在受控环境中运行不受信任的代码的)客户端与(选择加入该代码的通信的)远程主机之间进行全双工通信。用于此的安全模型是Web浏览器常用的基于原始的安全模式。 协议包括一个开放的握手以及随后的TCP层上的消息帧。 该技术的目标是为基于浏览器的、需要和服务器进行双向通信的(服务器不能依赖于打开多个HTTP连接(例如,使用XMLHttpRequest或iframe和长轮询))应用程序提供一种通信机制。

这里写图片描述

gorilla/websocket

A WebSocket implementation for Go.

github地址:
https://github.com/gorilla/websocket

Star: 4307

获取:

go get github.com/gorilla/websocket
   
  • 1

Server

其中,用到了satori/go.uuid:
Go实战–golang生成uuid(The way to go)

server.go

package mainimport (    "encoding/json"    "fmt"    "net/http"    "github.com/gorilla/websocket"    "github.com/satori/go.uuid")type ClientManager struct {    clients    map[*Client]bool    broadcast  chan []byte    register   chan *Client    unregister chan *Client}type Client struct {    id     string    socket *websocket.Conn    send   chan []byte}type Message struct {    Sender    string `json:"sender,omitempty"`    Recipient string `json:"recipient,omitempty"`    Content   string `json:"content,omitempty"`}var manager = ClientManager{    broadcast:  make(chan []byte),    register:   make(chan *Client),    unregister: make(chan *Client),    clients:    make(map[*Client]bool),}func (manager *ClientManager) start() {    for {        select {        case conn := <-manager.register:            manager.clients[conn] = true            jsonMessage, _ := json.Marshal(&Message{Content: "/A new socket has connected."})            manager.send(jsonMessage, conn)        case conn := <-manager.unregister:            if _, ok := manager.clients[conn]; ok {                close(conn.send)                delete(manager.clients, conn)                jsonMessage, _ := json.Marshal(&Message{Content: "/A socket has disconnected."})                manager.send(jsonMessage, conn)            }        case message := <-manager.broadcast:            for conn := range manager.clients {                select {                case conn.send <- message:                default:                    close(conn.send)                    delete(manager.clients, conn)                }            }        }    }}func (manager *ClientManager) send(message []byte, ignore *Client) {    for conn := range manager.clients {        if conn != ignore {            conn.send <- message        }    }}func (c *Client) read() {    defer func() {        manager.unregister <- c        c.socket.Close()    }()    for {        _, message, err := c.socket.ReadMessage()        if err != nil {            manager.unregister <- c            c.socket.Close()            break        }        jsonMessage, _ := json.Marshal(&Message{Sender: c.id, Content: string(message)})        manager.broadcast <- jsonMessage    }}func (c *Client) write() {    defer func() {        c.socket.Close()    }()    for {        select {        case message, ok := <-c.send:            if !ok {                c.socket.WriteMessage(websocket.CloseMessage, []byte{})                return            }            c.socket.WriteMessage(websocket.TextMessage, message)        }    }}func main() {    fmt.Println("Starting application...")    go manager.start()    http.HandleFunc("/ws", wsPage)    http.ListenAndServe(":12345", nil)}func wsPage(res http.ResponseWriter, req *http.Request) {    conn, error := (&websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}).Upgrade(res, req, nil)    if error != nil {        http.NotFound(res, req)        return    }    client := &Client{id: uuid.NewV4().String(), socket: conn, send: make(chan []byte)}    manager.register <- client    go client.read()    go client.write()}
   
  • 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

Go Client

package mainimport (    "flag"    "fmt"    "net/url"    "time"    "github.com/gorilla/websocket")var addr = flag.String("addr", "localhost:12345", "http service address")func main() {    u := url.URL{Scheme: "ws", Host: *addr, Path: "/ws"}    var dialer *websocket.Dialer    conn, _, err := dialer.Dial(u.String(), nil)    if err != nil {        fmt.Println(err)        return    }    go timeWriter(conn)    for {        _, message, err := conn.ReadMessage()        if err != nil {            fmt.Println("read:", err)            return        }        fmt.Printf("received: %s\n", message)