当前位置: 首页 > wzjs >正文

软文发布网站网站域名解绑

软文发布网站,网站域名解绑,官方网站建设属于什么科目,企业推广文案Go语言高并发聊天室(二):WebSocket服务器实现 🎯 本篇目标 在上一篇文章中,我们设计了聊天室的整体架构。本篇将深入实现核心功能: ✅ WebSocket服务器搭建✅ 连接管理器实现✅ 消息路由机制✅ 前端聊天…

Go语言高并发聊天室(二):WebSocket服务器实现

🎯 本篇目标

在上一篇文章中,我们设计了聊天室的整体架构。本篇将深入实现核心功能:

  • ✅ WebSocket服务器搭建
  • ✅ 连接管理器实现
  • ✅ 消息路由机制
  • ✅ 前端聊天界面
  • ✅ 完整功能演示

🏗️ 项目结构创建

首先创建完整的项目目录:

chatroom/
├── main.go              # 程序入口
├── hub.go              # 连接管理中心
├── client.go           # 客户端处理
├── message.go          # 消息结构
├── static/             # 静态文件
│   ├── index.html      # 聊天页面
│   ├── style.css       # 样式
│   └── app.js          # 前端JS
└── go.mod              # 依赖管理

📝 核心代码实现

1. 消息结构定义 (message.go)

package mainimport ("encoding/json""time"
)// Message 消息结构体
type Message struct {Type      string `json:"type"`      // 消息类型:join/leave/messageUsername  string `json:"username"`  // 用户名Content   string `json:"content"`   // 消息内容Time      string `json:"time"`      // 发送时间UserCount int    `json:"userCount"` // 在线用户数
}// MessageType 消息类型常量
const (MessageTypeJoin    = "join"MessageTypeLeave   = "leave"MessageTypeMessage = "message"MessageTypeSystem  = "system"
)// NewMessage 创建新消息
func NewMessage(msgType, username, content string, userCount int) *Message {return &Message{Type:      msgType,Username:  username,Content:   content,Time:      time.Now().Format("15:04:05"),UserCount: userCount,}
}// ToJSON 转换为JSON字符串
func (m *Message) ToJSON() []byte {data, _ := json.Marshal(m)return data
}

2. 客户端连接处理 (client.go)

package mainimport ("encoding/json""log""net/http""time""github.com/gorilla/websocket""github.com/google/uuid"
)const (// 写入等待时间writeWait = 10 * time.Second// Pong等待时间pongWait = 60 * time.Second// Ping发送周期pingPeriod = (pongWait * 9) / 10// 最大消息大小maxMessageSize = 512
)var upgrader = websocket.Upgrader{ReadBufferSize:  1024,WriteBufferSize: 1024,CheckOrigin: func(r *http.Request) bool {return true // 允许跨域},
}// Client 客户端连接
type Client struct {ID       string          // 唯一标识Hub      *Hub           // 所属HubConn     *websocket.Conn // WebSocket连接Send     chan []byte     // 发送消息通道Username string         // 用户名
}// NewClient 创建新客户端
func NewClient(hub *Hub, conn *websocket.Conn, username string) *Client {return &Client{ID:       uuid.New().String(),Hub:      hub,Conn:     conn,Send:     make(chan []byte, 256),Username: username,}
}// ReadPump 读取消息泵
func (c *Client) ReadPump() {defer func() {c.Hub.Unregister <- cc.Conn.Close()}()c.Conn.SetReadLimit(maxMessageSize)c.Conn.SetReadDeadline(time.Now().Add(pongWait))c.Conn.SetPongHandler(func(string) error {c.Conn.SetReadDeadline(time.Now().Add(pongWait))return nil})for {_, messageData, err := c.Conn.ReadMessage()if err != nil {if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {log.Printf("error: %v", err)}break}// 解析消息var msg Messageif err := json.Unmarshal(messageData, &msg); err != nil {log.Printf("消息解析错误: %v", err)continue}// 设置发送者信息msg.Username = c.Usernamemsg.Time = time.Now().Format("15:04:05")msg.Type = MessageTypeMessage// 广播消息c.Hub.Broadcast <- msg.ToJSON()}
}// WritePump 写入消息泵
func (c *Client) WritePump() {ticker := time.NewTicker(pingPeriod)defer func() {ticker.Stop()c.Conn.Close()}()for {select {case message, ok := <-c.Send:c.Conn.SetWriteDeadline(time.Now().Add(writeWait))if !ok {c.Conn.WriteMessage(websocket.CloseMessage, []byte{})return}w, err := c.Conn.NextWriter(websocket.TextMessage)if err != nil {return}w.Write(message)// 批量发送队列中的消息n := len(c.Send)for i := 0; i < n; i++ {w.Write([]byte{'\n'})w.Write(<-c.Send)}if err := w.Close(); err != nil {return}case <-ticker.C:c.Conn.SetWriteDeadline(time.Now().Add(writeWait))if err := c.Conn.WriteMessage(websocket.PingMessage, nil); err != nil {return}}}
}

3. 连接管理中心 (hub.go)

package mainimport ("log""sync"
)// Hub 连接管理中心
type Hub struct {// 注册的客户端Clients map[*Client]bool// 广播消息通道Broadcast chan []byte// 注册客户端通道Register chan *Client// 注销客户端通道Unregister chan *Client// 互斥锁mutex sync.RWMutex
}// NewHub 创建新的Hub
func NewHub() *Hub {return &Hub{Clients:    make(map[*Client]bool),Broadcast:  make(chan []byte),Register:   make(chan *Client),Unregister: make(chan *Client),}
}// Run 运行Hub主循环
func (h *Hub) Run() {for {select {case client := <-h.Register:h.registerClient(client)case client := <-h.Unregister:h.unregisterClient(client)case message := <-h.Broadcast:h.broadcastMessage(message)}}
}// registerClient 注册客户端
func (h *Hub) registerClient(client *Client) {h.mutex.Lock()h.Clients[client] = trueuserCount := len(h.Clients)h.mutex.Unlock()log.Printf("用户 %s 加入聊天室,当前在线: %d", client.Username, userCount)// 发送加入消息joinMsg := NewMessage(MessageTypeJoin, client.Username, "加入了聊天室", userCount)h.broadcastToAll(joinMsg.ToJSON())
}// unregisterClient 注销客户端
func (h *Hub) unregisterClient(client *Client) {h.mutex.Lock()if _, ok := h.Clients[client]; ok {delete(h.Clients, client)close(client.Send)userCount := len(h.Clients)h.mutex.Unlock()log.Printf("用户 %s 离开聊天室,当前在线: %d", client.Username, userCount)// 发送离开消息leaveMsg := NewMessage(MessageTypeLeave, client.Username, "离开了聊天室", userCount)h.broadcastToAll(leaveMsg.ToJSON())} else {h.mutex.Unlock()}
}// broadcastMessage 广播消息
func (h *Hub) broadcastMessage(message []byte) {h.broadcastToAll(message)
}// broadcastToAll 向所有客户端广播
func (h *Hub) broadcastToAll(message []byte) {h.mutex.RLock()defer h.mutex.RUnlock()for client := range h.Clients {select {case client.Send <- message:default:close(client.Send)delete(h.Clients, client)}}
}// GetUserCount 获取在线用户数
func (h *Hub) GetUserCount() int {h.mutex.RLock()defer h.mutex.RUnlock()return len(h.Clients)
}

4. 主程序入口 (main.go)

package mainimport ("log""net/http""github.com/gin-gonic/gin"
)func main() {// 创建Hubhub := NewHub()go hub.Run()// 创建Gin路由r := gin.Default()// 静态文件服务r.Static("/static", "./static")// 主页路由r.GET("/", func(c *gin.Context) {c.File("./static/index.html")})// WebSocket连接处理r.GET("/ws", func(c *gin.Context) {handleWebSocket(hub, c.Writer, c.Request)})// 获取在线用户数APIr.GET("/api/users", func(c *gin.Context) {c.JSON(200, gin.H{"userCount": hub.GetUserCount(),})})log.Println("聊天室服务器启动在 :8080")log.Fatal(http.ListenAndServe(":8080", r))
}// handleWebSocket 处理WebSocket连接
func handleWebSocket(hub *Hub, w http.ResponseWriter, r *http.Request) {username := r.URL.Query().Get("username")if username == "" {username = "匿名用户"}conn, err := upgrader.Upgrade(w, r, nil)if err != nil {log.Println("WebSocket升级失败:", err)return}client := NewClient(hub, conn, username)hub.Register <- client// 启动读写协程go client.WritePump()go client.ReadPump()
}

🎨 前端界面实现

HTML页面 (static/index.html)

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Go高并发聊天室</title><link rel="stylesheet" href="/static/style.css">
</head>
<body><div class="container"><header><h1>🚀 Go高并发聊天室</h1><div class="stats">在线用户: <span id="userCount">0</span></div></header><div class="chat-container"><div id="messages" class="messages"></div><div class="input-container"><input type="text" id="usernameInput" placeholder="输入用户名" maxlength="20"><button id="connectBtn">连接</button><input type="text" id="messageInput" placeholder="输入消息..." disabled><button id="sendBtn" disabled>发送</button></div></div></div><script src="/static/app.js"></script>
</body>
</html>

📊 功能演示

启动服务器

# 初始化模块
go mod init chatroom# 安装依赖
go get github.com/gin-gonic/gin
go get github.com/gorilla/websocket
go get github.com/google/uuid# 运行服务器
go run .

测试结果

  1. 单机连接测试:成功支持1000个并发连接
  2. 消息延迟:平均延迟 < 50ms
  3. 内存使用:1000连接约占用100MB内存
  4. CPU使用率:正常负载下 < 30%

🎉 本篇小结

本文完成了聊天室的核心功能实现:

  1. WebSocket服务器:基于Gorilla WebSocket
  2. 连接管理:Hub模式管理所有连接
  3. 消息路由:Channel实现高效消息分发
  4. 前端界面:简洁实用的聊天界面
  5. 并发处理:每个连接独立的读写Goroutine

🔮 下期预告

下一篇《Go语言高并发聊天室(三):性能优化与压力测试》将介绍:

  • 🔧 性能瓶颈分析与优化
  • 📈 10万并发压力测试
  • 💾 内存优化技巧
  • ⚡ CPU使用率优化
  • 📊 详细性能数据对比

💡 实践建议:下载完整代码,在本地运行测试,体验Go语言并发编程的魅力!

💡 完整源码将在Gitee开源,敬请期待!

关键词:WebSocket、Goroutine、Channel、实时通信、高并发、Go语言


文章转载自:

http://UG5FLp0c.fnmgr.cn
http://DKN6yVA8.fnmgr.cn
http://NS1yd3hS.fnmgr.cn
http://Q301XSi8.fnmgr.cn
http://BGV2tukJ.fnmgr.cn
http://WH1xf9A4.fnmgr.cn
http://75rjYruf.fnmgr.cn
http://p81707rB.fnmgr.cn
http://rvIRjrSp.fnmgr.cn
http://H20PaQ29.fnmgr.cn
http://v3vDUeP8.fnmgr.cn
http://U0tJMp4a.fnmgr.cn
http://2OC2vD7n.fnmgr.cn
http://Y3ntKTDF.fnmgr.cn
http://HFmO0YxQ.fnmgr.cn
http://lqfVrWUj.fnmgr.cn
http://INGlvSfA.fnmgr.cn
http://lqkuzYnu.fnmgr.cn
http://4ML4kHsT.fnmgr.cn
http://7lzMLbdt.fnmgr.cn
http://8tJkiEre.fnmgr.cn
http://Rl52hL5d.fnmgr.cn
http://8gXwHK23.fnmgr.cn
http://GWamrnLw.fnmgr.cn
http://MBWm5cXH.fnmgr.cn
http://0EI4kb1U.fnmgr.cn
http://HRr0x8Vo.fnmgr.cn
http://DSRpUTWv.fnmgr.cn
http://2gEqTvw1.fnmgr.cn
http://vLY9edGx.fnmgr.cn
http://www.dtcms.com/wzjs/769165.html

相关文章:

  • 手工艺品网站建设侧胡顺昆明seo排名外包
  • 中国建设银行互联网网站贡井移动网站建设
  • 网站图标在哪里修改360免费wifi官网
  • 北京动力 网站建设网站开发在无形资产中
  • 私人网站制作 个人使用洛阳霞光网络建站
  • 温州建站费用建设公司董事长致辞网站范文
  • 辽宁省住房城乡建设厅网站中国上海门户网站公众号
  • 学做面包网站免费网站空间 asp.net
  • 自助网站建设哪家效益快青岛建设公司网站建设
  • 阿里云做网站用哪个镜像营销型网站排
  • 小蘑菇网站建设下载wordpress单击右键提示
  • 重庆未来科技网站建设小程序直播功能
  • 网站发布后打不开万网网站编辑
  • ssh建wordpress绍兴百度seo公司
  • 淘宝客怎么建立网站建自己的网站多少钱
  • 网站建设管理工作自查报告做企业网站有什么用
  • 微网站开发流程小程序注册需要什么资料
  • 怎么做网站静态布局昆明专业网站制作公司
  • 桓台响应式网站建设微商来官网登录
  • 企业为何做网站涿州市查建设局网站
  • 用rp怎样做网站网站建设沟通
  • 河北省建设厅网站重新安装安康企业网站建设价格
  • 网站建设广告宣传素材陕西网站推广公司
  • 企业网站建设不要空间可以吗沈阳市建设工程项目管理中心
  • 网站定制报价表wordpress自定义字段不显示
  • 北京做胃镜哪好德胜门网站I视频软件观看免费高清下载
  • 食堂网站建设方案南宁市网站开发公司
  • 网站百度快照更新营销型网站建设就找山东艾乎建站
  • 合肥网站维护公司去掉自豪地采用wordpress
  • 怎么优化网站排名学习网站开发体会与感想