I. Cách Hệ Thống Hoạt Động
Trong bài viết này, tôi sẽ giới thiệu cách tạo một ứng dụng chat thời gian thực sử dụng Websocket và Golang. Chúng ta sẽ có hai kênh chat: Alice và Bob. Khi Alice gửi tin nhắn, nó sẽ được gửi đến máy chủ Websocket với kênh là Alice. Dữ liệu sẽ được máy chủ nhận và chuyển tiếp đến kênh của Bob, qua đó Bob có thể đọc được tin nhắn. Quá trình này sẽ lặp lại theo chiều ngược lại.
II. Triển Khai
1. Phần Server (Back-end)
go
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
var mapWsConn = make(map[string]*websocket.Conn)
func main() {
http.HandleFunc("/chat", LoadPageChat)
http.HandleFunc("/ws", InitWebsocket)
log.Fatal(http.ListenAndServe(":3000", nil))
}
Hàm main
khởi tạo hai API: tải trang chat và khởi tạo máy chủ Websocket. Máy chủ sẽ lắng nghe tại cổng 3000.
go
func LoadPageChat(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
path, err := os.Getwd()
if err != nil {
fmt.Fprintf(w, "%s", "error")
return
}
content, err := os.ReadFile(path + "/chat-using-websocket/chat.html")
if err != nil {
fmt.Fprintf(w, "%s", "error")
return
}
fmt.Fprintf(w, "%s", content)
}
Hàm LoadPageChat
sẽ đọc tệp chat.html
để xử lý giao diện người dùng. API này sẽ trả về HTML để hiển thị trên front-end cho người dùng.
go
func InitWebsocket(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
channel := r.URL.Query().Get("channel")
if r.Header.Get("Origin") != "http://" + r.Host {
fmt.Fprintf(w, "%s", "error")
return
}
if _, ok := mapWsConn[channel]; !ok {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
fmt.Fprintf(w, "%s", "error")
return
}
mapWsConn[channel] = conn
}
for {
var msg map[string]string
err := mapWsConn[channel].ReadJSON(&msg)
if err != nil {
fmt.Println("Error reading JSON:", err)
break
}
fmt.Printf("Received: %s\n", msg)
otherConn := getConn(channel)
if otherConn == nil {
continue
}
err = otherConn.WriteJSON(msg)
if err != nil {
fmt.Println("Error writing JSON:", err)
break
}
}
}
func getConn(channel string) *websocket.Conn {
for key, conn := range mapWsConn {
if key != channel {
return conn
}
}
return nil
}
Hàm InitWebsocket
sẽ khởi tạo kết nối websocket. Chúng ta sẽ tiêu thụ theo kênh để nhận tin nhắn và chuyển tiếp tới kênh khác.
Ví dụ: Alice gửi tin nhắn "Chào" đến kênh Alice -> kênh Alice sẽ nhận được "Chào" -> gửi tin nhắn này đến kênh Bob.
2. Phần Giao Diện Người Dùng (Front-end)
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ứng Dụng Chat</title>
</head>
<body>
<div class="container">
<div class="chat">
<div class="santaSays">
<div class="text-box-santa">
<div class="text">
<p>Chào, con yêu!</p>
<p>Con cần gì ở Santa?</p>
</div>
</div>
</div>
<div class="userSays">
<div class="text">
<p>Chào Santa!</p>
<p>Con muốn biết khi nào Santa sẽ mang quà cho con?</p>
</div>
</div>
</div>
<hr>
<div class="message-box">
<div class="message-input">
<input id="inputText" type="text" placeholder="Con cần gì?">
</div>
<div class="send-btn">
<i class="fa-solid fa-paper-plane plane"></i>
</div>
</div>
</div>
</body>
</html>
Giao diện của ứng dụng chat.
javascript
<script>
const chat = document.querySelector(".chat");
const inputText = document.getElementById("inputText");
let ws;
if (window.WebSocket === undefined) {
console.log("Trình duyệt của bạn không hỗ trợ WebSockets")
} else {
ws = initWS();
}
function initWS() {
let socket = new WebSocket("ws://" + window.location.host + "/ws" + window.location.search)
socket.onopen = function() {
console.log("Kết nối socket đã mở")
};
// nhận dữ liệu từ máy chủ
socket.onmessage = function (e) {
let pS = document.createElement("p");
pS.innerHTML = JSON.parse(e.data).message;
pS.classList.add("santaMessage");
chat.appendChild(pS);
chat.scrollTop = chat.scrollHeight;
}
// đóng kết nối socket
socket.onclose = function () {
console.log("Kết nối socket đã đóng")
}
return socket;
}
inputText.addEventListener("keyup", (e) => {
if (e.key === "Enter") {
let pU = document.createElement("p");
pU.innerHTML = inputText.value;
pU.classList.add("userMessage");
chat.appendChild(pU);
chat.scrollTop = chat.scrollHeight;
ws.send(JSON.stringify({message: inputText.value}));
inputText.value = "";
}
})
</script>
Mã JavaScript này sẽ tải trang, khởi tạo websocket, gửi tin nhắn đến máy chủ Websocket và hiển thị nó trên giao diện người dùng.
III. Kết Quả
Video demo sẽ được cung cấp ở phần dưới. Ứng dụng hoàn thiện sẽ cho phép người dùng chat với nhau một cách liền mạch và hiệu quả!
IV. Tài Liệu Tham Khảo
- Mã nguồn HTML: CodePen cảm ơn bạn đã giúp đỡ!
- Mã nguồn Golang: GitHub
- Bài viết của tôi trên blog: Hãy đọc tại đây
source: viblo