[中间件]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、功能增强
可以添加用户身份验证、消息历史记录等功能来完善聊天室

posted @ 2025-05-28 11:41  harrylearn66666  阅读(31)  评论(0)    收藏  举报