forked from AJRDRGZ/EDWhatsApp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.go
128 lines (104 loc) · 2.55 KB
/
client.go
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
package main
import (
"fmt"
"log"
"net/http"
"time"
"github.com/gorilla/websocket"
)
const (
// Maximum message size allowed.
maxMessageSize = 512
// Time allowed to write a message.
writeWait = 10 * time.Second
// Send pings to peer with this period.
pingPeriod = time.Minute
// Time allowed to read the next pong message from the peer.
// Must be greater than pingPeriod
pongWait = pingPeriod + (10 * time.Second)
)
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
type Message struct {
Nickname string `json:"nickname,omitempty"`
Content string `json:"content,omitempty"`
}
type Client struct {
nickname string
hub *Hub
conn *websocket.Conn
queueMessage chan Message
}
func (c *Client) readWS() {
defer func() {
c.hub.unregister <- c
c.conn.Close()
}()
c.conn.SetReadLimit(maxMessageSize)
c.conn.SetReadDeadline(time.Now().Add(pongWait))
c.conn.SetPongHandler(func(ping string) error {
fmt.Println("Pong:", c.nickname, ping)
c.conn.SetReadDeadline(time.Now().Add(pongWait))
return nil
})
for {
message := Message{}
if err := c.conn.ReadJSON(&message); err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
log.Println("can't read the message: ", err)
}
return
}
c.hub.broadcast <- message
}
}
func (c *Client) writeWS() {
ticker := time.NewTicker(pingPeriod)
defer func() {
ticker.Stop()
c.conn.Close()
}()
for {
select {
case message, isOpen := <-c.queueMessage:
if !isOpen {
// returns because the channel was closed by the hub
return
}
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
if err := c.conn.WriteJSON(message); err != nil {
log.Println("can't write the message into ws: ", err)
return
}
case <-ticker.C:
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
if err := c.conn.WriteMessage(websocket.PingMessage, []byte("Ping")); err != nil {
log.Printf("it can't write the Ping message: %v", err)
return
}
}
}
}
func handleWS(hub *Hub, w http.ResponseWriter, r *http.Request) {
nickname := r.URL.Query()["nickname"]
if len(nickname) != 1 {
w.WriteHeader(http.StatusBadRequest)
return
}
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println("cannot get the websocket connection: ", err)
return
}
client := &Client{
nickname: nickname[0],
hub: hub,
conn: conn,
queueMessage: make(chan Message, 2),
}
client.hub.register <- client
go client.writeWS()
go client.readWS()
}