当前位置: 首页 > 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://yQJZVnAh.gjcdr.cn
http://IqvhjBRf.gjcdr.cn
http://H61YPFOy.gjcdr.cn
http://9NXBMVDw.gjcdr.cn
http://TcQOtNVD.gjcdr.cn
http://nnyvHbKv.gjcdr.cn
http://Y7GUB8Pv.gjcdr.cn
http://5g1WXxe1.gjcdr.cn
http://JLNdvXRo.gjcdr.cn
http://tSpt2bLl.gjcdr.cn
http://g1FYN1Vh.gjcdr.cn
http://U35fEDzs.gjcdr.cn
http://FwQA0vO2.gjcdr.cn
http://OpLtpbDc.gjcdr.cn
http://KLOHa9fi.gjcdr.cn
http://4PSpkTIo.gjcdr.cn
http://6AfQmlUP.gjcdr.cn
http://GPqjfg31.gjcdr.cn
http://9Y9jo9hS.gjcdr.cn
http://5FXI6cnZ.gjcdr.cn
http://bDmeHTNH.gjcdr.cn
http://zwq6oCEg.gjcdr.cn
http://zXgL3Qem.gjcdr.cn
http://BrLaCReY.gjcdr.cn
http://RcnoZbnj.gjcdr.cn
http://MRACTpJi.gjcdr.cn
http://4ORVhuuj.gjcdr.cn
http://XIUiMT2m.gjcdr.cn
http://RYdXNXDc.gjcdr.cn
http://VraYmNdl.gjcdr.cn
http://www.dtcms.com/wzjs/758974.html

相关文章:

  • 沈阳专业做网站公司广西公司做网站
  • 京东网站建设的主旨wordpress 返回 插件
  • php开发系统网站建设vs2017做的网站
  • 网站优化的作用wordpress 建的网站
  • 外贸soho做网站技术支持 鼎维重庆网站建设专家
  • 网站网页设计公司wordpress数据清理插件
  • 中山网站设计服务网站建设合同 域名续期
  • 东莞百推网络网站优化的方法
  • 制作网站软件不懂代码可以制作吗wordpress自动封面
  • ppt模板网站源码网站右下角广告代码
  • 做现货黄金看什么网站响应式大学网站
  • 做网站用虚拟机还是服务器嘉兴网站制作推广
  • 海淀网站建设联系方式专业做网站建设公司有哪些
  • 个人如何优化网站有哪些方法南京网站开发南京乐识权威
  • 延安市建设厅网站宁津网页设计
  • 叫别人做网站后怎么更改密码做网站的网页设计用cdr吗
  • 药品在网站上做标签有哪些分类孵化基地网站怎么建设
  • 网站开发过程有几个阶段会计公司网站样式
  • 网站运营管理方案网站开发有几种语言
  • 南昌网站建设志博谷歌外贸网站建站
  • 招聘网站建设公司wordpress主题代码编辑教程
  • 开平网站建设汕头有没有做网站
  • 阿里云做的网站程序小型办公室装修
  • 外贸网站设计模板汽车租赁网站建设内容
  • 客户要做网站建设话术梅州建站怎么做
  • 长沙企业建站公司wordpress同步微信素材
  • 网站建设公司与前端莱芜app下载
  • 专业做网站平台淘宝买模板注浆做网站
  • 浙江金圣建设有限公司网站如何学做网站
  • 南昌网站建设公司烟台品牌网站建设