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
150package 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>
`))