gin使用websocket实现群聊单聊
【摘要】 package mainimport ( "github.com/gin-gonic/gin" "github.com/gorilla/websocket" "log" "net/http" "sync")var ( upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Reques...
package main
import (
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"log"
"net/http"
"sync"
)
var (
upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
clients = make(map[*websocket.Conn]bool)
clientsMux = &sync.Mutex{}
)
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.File("chat.html")
})
r.GET("/ws", handleWebSocket)
r.Run(":8080")
}
func handleWebSocket(c *gin.Context) {
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
log.Println(err)
return
}
defer conn.Close()
clientsMux.Lock()
clients[conn] = true
clientsMux.Unlock()
for {
messageType, message, err := conn.ReadMessage()
if err != nil {
log.Println(err)
clientsMux.Lock()
delete(clients, conn)
clientsMux.Unlock()
break
}
log.Printf("Received: %s", message)
clientsMux.Lock()
for client := range clients {
if err := client.WriteMessage(messageType, message); err != nil {
log.Println(err)
clientsMux.Lock()
delete(clients, client)
clientsMux.Unlock()
}
}
clientsMux.Unlock()
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocket Chat</title>
<style>
#chat {
width: 300px;
height: 400px;
border: 1px solid #ccc;
overflow-y: scroll;
}
</style>
</head>
<body>
<h1>WebSocket Chat</h1>
<div id="chat"></div>
<input type="text" id="message" placeholder="Type a message...">
<button onclick="sendMessage()">Send</button>
<script>
var ws = new WebSocket("ws://localhost:8080/ws");
ws.onmessage = function(event) {
var chat = document.getElementById("chat");
var message = document.createElement("div");
message.textContent = event.data;
chat.appendChild(message);
chat.scrollTop = chat.scrollHeight;
};
function sendMessage() {
var message = document.getElementById("message").value;
ws.send(message);
document.getElementById("message").value = "";
}
</script>
</body>
</html>
为了实现单聊,我们需要对客户端进行标识,并在服务器端维护一个用户到连接的映射。
package main
import (
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"log"
"net/http"
"sync"
)
var (
upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
clients = make(map[string]*websocket.Conn)
clientsMux = &sync.Mutex{}
)
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.File("chat.html")
})
r.GET("/ws/:username", handleWebSocket)
r.Run(":8080")
}
func handleWebSocket(c *gin.Context) {
username := c.Param("username")
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
log.Println(err)
return
}
defer conn.Close()
clientsMux.Lock()
clients[username] = conn
clientsMux.Unlock()
for {
messageType, message, err := conn.ReadMessage()
if err != nil {
log.Println(err)
clientsMux.Lock()
delete(clients, username)
clientsMux.Unlock()
break
}
log.Printf("Received from %s: %s", username, message)
// 解析消息,假设消息格式为 "to:username:message"
parts := bytes.Split(message, []byte{':'})
if len(parts) != 3 || string(parts[0]) != "to" {
log.Println("Invalid message format")
continue
}
to := string(parts[1])
msg := parts[2]
clientsMux.Lock()
toConn, ok := clients[to]
clientsMux.Unlock()
if ok {
if err := toConn.WriteMessage(messageType, msg); err != nil {
log.Println(err)
}
} else {
log.Printf("User %s not found", to)
}
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocket Chat</title>
<style>
#chat {
width: 300px;
height: 400px;
border: 1px solid #ccc;
overflow-y: scroll;
}
</style>
</head>
<body>
<h1>WebSocket Chat</h1>
<div id="chat"></div>
<input type="text" id="to" placeholder="To username...">
<input type="text" id="message" placeholder="Type a message...">
<button onclick="sendMessage()">Send</button>
<script>
var username = prompt("Enter your username:");
var ws = new WebSocket("ws://localhost:8080/ws/" + username);
ws.onmessage = function(event) {
var chat = document.getElementById("chat");
var message = document.createElement("div");
message.textContent = event.data;
chat.appendChild(message);
chat.scrollTop = chat.scrollHeight;
};
function sendMessage() {
var to = document.getElementById("to").value;
var message = document.getElementById("message").value;
ws.send("to:" + to + ":" + message);
document.getElementById("message").value = "";
}
</script>
</body>
</html>
-
主程序 (
main.go
):- 用户标识:通过路由参数
:username
获取用户的标识。 - 消息解析:假设消息格式为
to:username:message
,解析消息并发送给指定的用户。
- 用户标识:通过路由参数
-
前端页面 (
chat.html
):- 用户标识:在连接 WebSocket 时,通过
prompt
获取用户的标识。 - 消息发送:在发送消息时,使用
to:username:message
格式。
- 用户标识:在连接 WebSocket 时,通过
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)