0
0
Lập trình
Hưng Nguyễn Xuân 1
Hưng Nguyễn Xuân 1xuanhungptithcm

Xây Dựng Ứng Dụng Chat Thời Gian Thực Bằng Websocket và Golang

Đăng vào 4 ngày trước

• 5 phút đọc

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 Copy
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 Copy
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 Copy
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 Copy
<!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 Copy
<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

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào