目的
使用go语言实现websocket服务端
逻辑
本示例主要使用gorilla/websocket框架将http请求升级成websocket协议
项目结构
.
├── go.mod
├── go.sum
├── index.html
├── main.go
└── socket.json
客户端
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>TestWebsocket</title>
<script type="text/javascript">
function LinkServer() {
// 声明连接
var Server_Com;
if ("WebSocket" in window) {
Server_Com = new WebSocket("ws://localhost:13000/getTime");
console.log("新建连接到->localhost:13000");
}
// 建立连接后发送
Server_Com.onopen = function() {
Server_Com.send("Hello Server!"); // Web Socket 已连接上,使用 send() 方法发送数据
console.log("已连接上服务器");
}
// 接收服务器消息
Server_Com.onmessage = function(event) {
var recv_msg = event.data;
if (recv_msg == "Hello Client!") {
console.log("接收到服务器的问候: " + recv_msg); // 用于提示收到信息
} else {
document.getElementById("Time").textContent = recv_msg; // 实时更新显示服务器发回的时间
console.log("接收到服务器数据: " + recv_msg);
}
}
}
</script>
</head>
<body>
<p>服务器时间:</p>
<p id="Time">2022-05-29 20:00:00</p>
<button onclick="LinkServer()">连接</button>
</body>
</html>
服务端
解决跨越问题
var upgrader = websocket.Upgrader{
// 解决跨域问题
CheckOrigin: func(r *http.Request) bool {
return true
},
}
main函数
func main() {
// 注册服务器事件
http.HandleFunc("/", Index)
http.HandleFunc("/getTime", SendTime) // 支持多端同时访问,相当于收到不同请求后未每个请求分别创建线程处理
fmt.Println("已向 DefaultServeMux 注册 SendTime 事件")
// 打开要侦听的前端请求连接端口
err := http.ListenAndServe(":13000", nil) // 这里是接受对本机所有的通过13000的请求,本机有多个IP则可在端口号前加IP地址区分,如"10.11.100.123:13000"
if err != nil {
fmt.Println("端口侦听错误:", err)
}
}
这里监听了2个路由:
- “/“:用于浏览器访问首页,通过
Index
读取index.html
文件并且返回 - “getTime”:
index.html
页面中js通过websocket连接到这个路由,通过SendTime函数处理请求并返回结果
main函数开启了tcp协议的13000端口,通过http服务向外暴露
Index
这个函数主要就是读取index.html
文件并返回给前端
func Index(w http.ResponseWriter, r *http.Request) {
index, err := ioutil.ReadFile("index.html")
if err != nil {
fmt.Println(err)
return
}
n, err := w.Write(index)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("n:", n)
}
SendTime
这个函数主要是将http连接转换成websocket连接,处理完成后循环返回数据
func SendTime(w http.ResponseWriter, r *http.Request) {
c, err := upgrader.Upgrade(w, r, nil)
if err != nil {
fmt.Print("升级websocket连接错误:", err)
return
}
defer c.Close()
// 接受消息
mt, message, err := c.ReadMessage()
if err != nil {
fmt.Println("接收错误:", err)
} else {
fmt.Println("接收到前端消息:", string(message))
// 发送问候
var sendbuff string = "Hello Client!"
c.WriteMessage(mt, []byte(sendbuff)) // 为阅读方便,省去错误处理
// 不停地循环发送时间
fmt.Println("开始发送时间")
for {
sendbuff = time.Now().Format("2006-01-02 15:04:05")
err = c.WriteMessage(mt, []byte(sendbuff))
if err != nil {
fmt.Println("发送错误:", err)
break
}
fmt.Println("发送时间:", sendbuff)
time.Sleep(1 * time.Second) // 间隔1s,降低资源消耗,如果想提高实时性可减少时间间隔
}
fmt.Println("停止发送时间")
}
}
运行
1.使用pm2后台运行服务:pm2 start socket.json
2.浏览器访问:localhost:13000
服务器端日志:
点击连接之后,页面上就可以实时展示服务器上的时间了
源代码:https://github.com/ZBIGBEAR/websocket
参考
[1]websocket
[2]golang服务端与web前端使用websocket通信
[3]Go-一个使用websocket的例子