直播商城源码,实现商城客服聊天,发送文字、图片的功能
1.实现的思路
由于之前写python的时候接触过websocket,但是当时是使用类似于广播的机制的,没有做过一对一的聊天.但是既然知道了广播,那一对一也就不是什么难事了
首先客户端连接上来时,服务器会实例化每个客户端的连接,并且保存这些连接,这时候只需要前端发送消息时,带有联系人的id 这样就可以根据id 找到联系人发送消息了
2.Demo 示例
下面是gin 实现的一个接口,使用 ws协议 连接该接口,然后就可以保存一个ws的连接
1 | <br> // 把 http 升级为 ws<br>func Login(c *gin.Context) {<br>tid := c.Query("tid")<br>userID , err := strconv.ParseInt(tid, 10, 64)<br>if err != nil {<br>c.JSON(http.StatusOK, gin.H{"code": 10, "arg-err": db.InvalidArgument})<br>return<br>}<br>Logger.Info(" ------ 请求头 ------", c.Request.Header)<br>Logger.Info("ws 连接请求")<br>userInfo, err := db.FindUser(userID)<br>if err != nil {<br>Logger.Info("ws 连接失败,找不到用户信息", err)<br>c.JSON(http.StatusOK, gin.H{"code": 10, "arg-err": db.InvalidArgument})<br>return<br>}<br>conn, err := Upgrader.Upgrade(c.Writer, c.Request, nil)<br>if err != nil {<br>Logger.Error("http 协议升级为ws 协议失败:", err)<br>return<br>}<br>uniqueID := utils.UUID()<br>wsClient := &Client{ID: utils.UUID(), Socket: conn, Send: make(chan []byte), UserInfo:userInfo, ConnID:uniqueID}<br>go wsClient.Read()<br>Manager.Register <- wsClient<br>Logger.Infof("ws 登陆成功 ip %v 用户id %v", conn.RemoteAddr(), *wsClient.UserInfo.TID)<br>} |
聊天功能demo
聊天功能主要是每个连接开了一个go 协程去检查该连接是否有消息,如果有消息 则检查它要发给哪个用户,找到那个用户的连接,发过去即可
1 | <br>func (c *Client) Read() {<br>defer func() {<br>Manager.Unregister <- c<br>c.Socket.Close()<br>}()<br> for {<br>Logger.Infof( "用户 %v 等待消息中...." , *c.UserInfo.TID)<br>_, message, err := c.Socket.ReadMessage()<br> if err != nil {<br>Logger.Error( "读取消息失败 " , err)<br>Manager.Unregister <- c<br>c.Socket.Close()<br> break <br>}<br>Logger.Info( "====== ws 消息 ====== " , string(message))<br> var content Message<br>err = json.Unmarshal(message, &content)<br> if err != nil {<br>Logger.Error( "接收消息失败 " , err)<br> continue <br>}<br> if content.Content == "logout" {<br>Manager.Unregister <- c<br>c.Socket.Close()<br> break <br>}<br> if (content.Recipient == 0 || len(content.Content) == 0) && len(content.Image) < 0 {<br>Logger.Error( "无效的消息 " )<br> continue <br>}<br> // 保存聊天记录<br>unRead := db.MessageUnRead<br>msgType := content.Type<br>chat := &db.Chat{}<br>fromUser := c.UserInfo.TID<br>chat.FromUser = fromUser<br>chat.ToUser = &content.Recipient<br>chat.Content = &content.Content<br>chat.Image = &content.Image<br>chat.Status = &unRead<br>chat.Type = &msgType<br>db.SaveChat(chat)<br>now := time.Now()<br>nowTimeStamp := db.JSONTime{Time:now}<br>content.MsgID = *chat.TID<br>content.Timestamp = nowTimeStamp<br>content.Sender = *fromUser<br>// 转发给另外一端<br>Logger.Infof("用户 %v 发消息 %v 给另外一个用户 %v ", *fromUser, content.Content, content.Recipient)<br>Manager.ChatTo(content.Recipient, &content)<br>}<br>}<br>func (manager *ClientManager) ChatTo(userID int64, msg *Message) {<br>manager.Clients.Range(func(k, v interface{}) bool {<br>if v != nil {<br>conn := v.(*Client)<br>if *conn.UserInfo.TID == userID {<br>message, err := json.Marshal(msg)<br>if err != nil {<br>Logger.Error("聊天失败")<br>return true<br>}<br>Logger.Info("发送给 ", *conn.UserInfo.TID)<br>err = conn.Socket.WriteMessage(websocket.TextMessage, message)<br>if err != nil {<br>Logger.Error("消息转发失败 ", err)<br>}<br>}<br>}<br>return true<br>})<br>} |
关于离线消息的处理
当联系人不在线时,我的处理方案是将聊天数据保存下来标记该消息未读,提供一个接口查询用户未读消息,当下次用户登陆时前端发http 请求未读消息即可
关于图片发送
这里我的处理方案是,写一个接口提供给前端上传图片上传成功时返回图片路径,前端发来的聊天内容只有图片的url,后续聊天图片显示通过url 请求图片即可
以上就是直播商城源码,实现商城客服聊天,发送文字、图片的功能, 更多内容欢迎关注之后的文章
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现