[中间件]websocket使用笔记
1、基本概念
websocket是一个全双工通信协议
在全双工通信中,通信双方都配备了发送和接收设备。例如,在以太网通信中,计算机的网卡既有发送数据的模块,也有接收数据的模块。这两个模块可以同时工作,就像在一段对话中,双方可以同时说话和听对方说话一样。数据在这种通信方式下能够在两个方向上同时进行传输,信息流是双向并行的。
1.1 与半双工和单工通信对比
半双工通信 :半双工通信是指通信双方都能发送和接收信息,但不能同时进行发送和接收。就像两个人用一个只能单向传递声音的管道来通信,一个人在说话的时候,另一个人只能听,不能同时说话。例如对讲机,按下通话键说话时,就不能接收对方的声音。
单工通信 :单工通信是指信息只能单方向传输。就像一个广播电台向收音机发送广播信号,收音机只能接收,不能向广播电台发送信号。全双工通信与这两种通信方式相比,具有更高的通信效率,因为它允许双方同时进行信息交互。
2、demo代码
后端代码
package main
import (
"fmt"
"log"
"net/http"
"sync"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
type Client struct {
Conn *websocket.Conn
}
type Room struct {
Clients []*Client
mu sync.Mutex
}
var room = Room{}
func main() {
http.HandleFunc("/ws", handleWebSocket)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "index.html")
})
fmt.Println("Server started on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func handleWebSocket(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println("升级连接失败:", err)
return
}
defer conn.Close()
client := &Client{Conn: conn}
room.mu.Lock()
room.Clients = append(room.Clients, client)
room.mu.Unlock()
for {
messageType, p, err := conn.ReadMessage()
if err != nil {
log.Println("读取消息失败:", err)
break
}
fmt.Printf("收到消息: %s\n", p)
room.mu.Lock()
for _, c := range room.Clients {
if c.Conn != conn {
err := c.Conn.WriteMessage(messageType, p)
if err != nil {
log.Println("发送消息失败:", err)
}
}
}
room.mu.Unlock()
}
}
前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebSocket 聊天室</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
#chatWindow {
height: 400px;
overflow-y: auto;
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
}
#messageInput {
width: calc(100% - 22px);
padding: 10px;
margin-bottom: 10px;
}
#sendButton {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
cursor: pointer;
}
</style>
</head>
<body>
<h1>WebSocket 聊天室</h1>
<div id="chatWindow"></div>
<input type="text" id="messageInput" placeholder="输入消息...">
<button id="sendButton">发送</button>
<script>
const wsUrl = 'ws://localhost:8080/ws';
const ws = new WebSocket(wsUrl);
const chatWindow = document.getElementById('chatWindow');
const messageInput = document.getElementById('messageInput');
const sendButton = document.getElementById('sendButton');
ws.onopen = function() {
appendMessage('已连接到聊天室');
};
ws.onmessage = function(event) {
appendMessage('收到消息: ' + event.data);
};
ws.onclose = function() {
appendMessage('已断开连接');
};
ws.onerror = function(error) {
appendMessage('错误: ' + error.message);
};
sendButton.onclick = function() {
const message = messageInput.value;
if (message) {
ws.send(message);
appendMessage('你: ' + message);
messageInput.value = '';
}
};
messageInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
sendButton.click();
}
});
function appendMessage(message) {
const p = document.createElement('p');
p.textContent = message;
chatWindow.appendChild(p);
chatWindow.scrollTop = chatWindow.scrollHeight;
}
</script>
</body>
</html>
运行代码
go mod init gin-websocket-demo
go mod tidy
go run main.go
3、功能增强
可以添加用户身份验证、消息历史记录等功能来完善聊天室

浙公网安备 33010602011771号