go使用websocket来做一个聊天室

后端

安装 websocket 库

在 Go 语言中,使用“github.com/gorilla/websocket”包提供了 WebSocket 相关的功能。可以通过以下命令来安装该包:

go get github.com/gorilla/websocket

导入项目中要用的包

import (
	"log"// 日志打印包
	"net/http"// 包含HTTP服务器和客户端功能

	"github.com/gorilla/websocket" // 包含WebSocket功能
)

定义消息结构体

  // Message结构体定义了消息的格式,包含用户名和消息内容
  type Message struct {
    
    
	Username string `json:"username"`
	Message  string `json:"message"`
  }

设置存储和消息通道

// clients是一个map,用于存储当前连接的所有客户端
var clients = make(map[*websocket.Conn]bool)

// broadcast是一个通道,用于广播消息给所有连接的客户端
var broadcast = make(chan Message)

处理 WebSocket 连接

func handleConnections(w http.ResponseWriter, r *http.Request) {
    
    
	// 创建一个WebSocket升级器
	upgrader := websocket.Upgrader{
    
    }

	// 将HTTP连接升级为WebSocket连接
	ws, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
    
    
		log.Fatal(err)
	}
	
	// 关闭WebSocket连接
	defer ws.Close()

	// 将新的客户端连接添加到clients映射中
	clients[ws] = true

	// 无限循环,用于读取客户端发送的消息
	for {
    
    
		var msg Message
		// 读取客户端发送的消息
		err := ws.ReadJSON(&msg)
		if err != nil {
    
    
			log.Printf("读取消息错误:%v", err)
			// 如果读取消息失败,删除客户端连接
			delete(clients, ws)
			break
		}
		log.Println(msg)

		// 将接收到的消息放入广播通道中
		broadcast <- msg

	}
}
// handleMessages函数处理消息广播
func handleMessages() {
    
    
	for {
    
    
		// 从广播通道中读取消息
		msg := <-broadcast

		// 遍历所有连接的客户端,将消息发送给每个客户端
		for client := range clients {
    
    
			err := client.WriteJSON(msg)
			if err != nil {
    
    
				log.Printf("发送消息错误:%v", err)
				// 如果发送消息失败,关闭客户端连接并删除
				client.Close()
				delete(clients, client)
			}
		}
	}
}

主函数


func main() {
    
    
	// 处理WebSocket连接的函数
	http.HandleFunc("/ws", handleConnections)

	// 启动一个goroutine来处理消息广播
	go handleMessages()

	// 启动HTTP服务器,监听端口8080
	log.Println("服务器启动,监听端口:8080")
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
    
    
		log.Fatal("监听端口出现问题: ", err)
	}
}

完整代码

package main

import (
	"log"      // 包含日志记录功能
	"net/http" // 包含HTTP服务器和客户端功能

	"github.com/gorilla/websocket" // 包含WebSocket功能
)

// clients是一个map,用于存储当前连接的所有客户端
var clients = make(map[*websocket.Conn]bool)

// broadcast是一个通道,用于广播消息给所有连接的客户端
var broadcast = make(chan Message)

// Message结构体定义了消息的格式,包含用户名和消息内容
type Message struct {
    
    
	Username string `json:"username"`
	Message  string `json:"message"`
}

var upgrader = websocket.Upgrader{
    
    
	CheckOrigin: func(r *http.Request) bool {
    
    
		return true // Allow all origins (not recommended for production)
	},
}

func main() {
    
    
	// 处理WebSocket连接的函数
	http.HandleFunc("/ws", handleConnections)

	// 启动一个goroutine来处理消息广播
	go handleMessages()

	// 启动HTTP服务器,监听端口8080
	log.Println("服务器启动,监听端口:8080")
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
    
    
		log.Fatal("监听端口出现问题: ", err)
	}
}

// handleConnections函数处理WebSocket连接
func handleConnections(w http.ResponseWriter, r *http.Request) {
    
    
	// 将HTTP连接升级为WebSocket连接
	ws, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
    
    
		log.Fatal(err)
	}

	// 关闭WebSocket连接
	defer ws.Close()

	// 将新的客户端连接添加到clients映射中
	clients[ws] = true

	// 无限循环,用于读取客户端发送的消息
	for {
    
    
		var msg Message
		// 读取客户端发送的消息
		if err := ws.ReadJSON(&msg); err != nil {
    
    
			log.Printf("读取消息错误:%v", err)
			// 如果读取消息失败,删除客户端连接
			delete(clients, ws)
			break
		}
		log.Println(msg)

		// 将接收到的消息放入广播通道中
		broadcast <- msg

	}
}

// handleMessages函数处理消息广播
func handleMessages() {
    
    
	for {
    
    
		// 从广播通道中读取消息
		msg := <-broadcast

		// 遍历所有连接的客户端,将消息发送给每个客户端
		for client := range clients {
    
    
			if err := client.WriteJSON(msg); err != nil {
    
    
				log.Printf("发送消息错误:%v", err)
				// 如果发送消息失败,关闭客户端连接并删除
				client.Close()
				delete(clients, client)
			}
		}
	}
}


前端

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Websocket 聊天室</title>

    <!-- 定义样式 -->
    <style>
      #message-box {
      
      
        height: 500px;
        overflow-y: scroll;
      }
    </style>
  </head>

  <body>
    <h1>Websocket 聊天室</h1>

    <!-- 消息显示框 -->
    <div id="message-box"></div>

    <!-- 消息发送表单 -->
    <form id="message-form" onsubmit="sendMessage(event)">
      <input type="text" id="username" placeholder="请输入用户名" required />
      <br />
      <input type="text" id="message" placeholder="请输入消息" required />
      <br />
      <button type="submit">发送</button>
    </form>

    <script>
      // 创建 WebSocket 连接
      const socket = new WebSocket("ws://localhost:8080/ws");
      // 当连接打开时
      socket.onmessage = function (event) {
      
      
        // 解析接收到的数据
        const data = JSON.parse(event.data);
        // 获取消息显示框
        const messageBox = document.getElementById("message-box");
        // 创建消息元素
        const messageElement = document.createElement("p");
        // 设置消息元素的文本内容
        messageElement.innerText = data.username + ": " + data.message;
        // 将消息元素添加到消息显示框中
        messageBox.appendChild(messageElement);
      };
      // 当连接关闭时
      function sendMessage(event) {
      
      
        // 阻止表单的默认提交行为
        event.preventDefault();

        // 获取用户名和消息输入框的值
        const username = document.getElementById("username").value;
        const message = document.getElementById("message").value;

        // 创建要发送的数据对象
        const data = {
      
      
          username: username,
          message: message,
        };

        // 通过 WebSocket 发送数据
        socket.send(JSON.stringify(data));
        // 清空消息输入框
        document.getElementById("message").value = "";
      }
    </script>
  </body>
</html>

任务完成

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_73626494/article/details/143089612