返回顶部
首页 > 资讯 > 精选 >怎么使用Go+WebSocket快速实现一个chat服务
  • 873
分享到

怎么使用Go+WebSocket快速实现一个chat服务

2023-06-14 10:06:33 873人浏览 独家记忆
摘要

这篇文章将为大家详细讲解有关怎么使用Go+websocket快速实现一个chat服务,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。前言在 go-zero 开源之后,非常多的用户询问是否可以支持以及什么时候

这篇文章将为大家详细讲解有关怎么使用Go+websocket快速实现一个chat服务,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

前言

在 go-zero 开源之后,非常多的用户询问是否可以支持以及什么时候支持 WEBSocket,终于在 v1.1.6 里面我们从框架层面让websocket 的支持落地了,下面我们就以 chat 作为一个示例来讲解如何用 go-zero 来实现一个 websocket 服务。

整体设计

我们以 zero-example 中的 chat 聊天室为例来一步步一讲解 websocket 的实现,分为如下几个部分:

  • 多客户端接入

  • 消息广播

  • 客户端的及时上线下线

  • 全双工通信【客户端本身是发送端,也是接收端】

先放一张图,大致的数据传输:

怎么使用Go+WebSocket快速实现一个chat服务

中间有个 select loop 就是整个 chat 的 engine。首先要支撑双方通信:

  • 得有一个交流数据的管道。客户端只管从 管道 读取/输送数据;

  • 客户端在线情况。不能说你下线了,还往你那传输数据;

数据流

数据流是 engine 的主要功能,先不急着看代码,我们先想 client 怎么接入并被 engine 感知:

  • 首先是从前端发 websocket 请求;

  • 建立连接;准备接收/发送通道;

  • 注册到 engine;

怎么使用Go+WebSocket快速实现一个chat服务

// html 操作 {js}if (window["WebSocket"]) { conn = new WebSocket("ws://" + document.location.host + "/ws"); conn.onclose = function (evt) {  var item = document.createElement("div");  item.innerHTML = "<b>Connection closed.</b>";  appendLog(item); }; ...}// 路由engine.AddRoute(rest.Route{ Method: Http.MethodGet, Path:  "/ws", Handler: func(w http.ResponseWriter, r *http.Request) {  internal.ServeWs(hub, w, r) },})// 接入逻辑func ServeWs(hub *Hub, w http.ResponseWriter, r *http.Request) { // 将http请求升级为websocket conn, err := upgrader.Upgrade(w, r, nil) ... // 构建client:hub{engine}, con{websocker conn}, send{channel buff} client := &Client{ hub: hub, conn: conn, send: make(chan []byte, bufSize), } client.hub.reGISter <- client // 开始客户端双工的通信,接收和写入数据 go client.writePump() go client.readPump()}

这样,新接入的 client 就被加入到 注册 通道中。

hub engine

发出了 注册 的动作,engine 会怎么处理呢?

type Hub struct { clients map[*Client]bool // 上线clients broadcast chan []byte  // 客户端发送的消息 ->广播给其他的客户端 register chan *Client   // 注册channel,接收注册msg unregister chan *Client  // 下线channel}func (h *Hub) Run() { for { select {  // 注册channel:存放到注册表中,数据流也就在这些client中发生 case client := <-h.register:  h.clients[client] = true  // 下线channel:从注册表里面删除 case client := <-h.unregister:  if _, ok := h.clients[client]; ok {  delete(h.clients, client)  close(client.send)  }  // 广播消息:发送给注册表中的client中,send接收到并显示到client上 case message := <-h.broadcast:  for client := range h.clients {  select {  case client.send <- message:  default:   close(client.send)   delete(h.clients, client)  }  } } }}

接收注册消息 -> 加入全局注册表

如果 engine.broadcast 接收到,会将 msg 传递给 注册表 的 client.sendChan
这样从 HTML -> client -> hub -> other client 的整个数据流就清晰了。

广播数据

上面说到 engine.broadcast 接收到数据,那从页面开始,数据是怎么发送到这?

func (c *Client) readPump() { ... for {  // 1 _, message, err := c.conn.ReadMessage() if err != nil {  if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnORMalClosure) {  log.Printf("error: %v", err)  }  break } message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1))  // 2. c.hub.broadcast <- message }}
  • 从 conn 中不断读取 msg【页面点击后传递】

  • 将 msg 传入 engine.broadcast,从而广播到其他的 client

  • 当出现发送异常或者是超时,异常退出时,会触发下线 client

同时要知道,此时发送消息的 client 不止有一个,可能会有很多个。那发送到其他client,client 从自己的 send channel 中读取消息即可:

func (c *Client) writePump() { // 写超时控制 ticker := time.NewTicker(pingPeriod) ... for { select { case message, ok := <-c.send:   // 当接收消息写入时,延长写超时时间。  c.conn.SetWriteDeadline(time.Now().Add(writeWait))  ...  w, err := c.conn.NextWriter(websocket.TextMessage)  ...  w.Write(message)  // 依次读取 send 中消息,并write  n := len(c.send)  for i := 0; i < n; i++ {  w.Write(newline)  w.Write(<-c.send)  }   ... case <-ticker.C:  c.conn.SetWriteDeadline(time.Now().Add(writeWait))  ... } }}

上面也说了,send 有来自各自客户端中发送的msg:所以当检测到 send 有数据,就不断接收消息并写入当前 client;同时当写超时,会检测websocket长连接是否还存活,存活则继续读 send chan,断开则直接返回。

关于“怎么使用Go+WebSocket快速实现一个chat服务”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

--结束END--

本文标题: 怎么使用Go+WebSocket快速实现一个chat服务

本文链接: https://lsjlt.com/news/269783.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 怎么使用Go+WebSocket快速实现一个chat服务
    这篇文章将为大家详细讲解有关怎么使用Go+WebSocket快速实现一个chat服务,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。前言在 go-zero 开源之后,非常多的用户询问是否可以支持以及什么时候...
    99+
    2023-06-14
  • 用Go+WebSocket快速实现一个chat服务
    前言 在 go-zero 开源之后,非常多的用户询问是否可以支持以及什么时候支持 websocket,终于在 v1.1.6 里面我们从框架层面让websocket 的支持落地了,下...
    99+
    2024-04-02
  • 用Go+WebSocket快速实现一个chat服务
    前言 在 go-zero 开源之后,非常多的用户询问是否可以支持以及什么时候支持 websocket,终于在 v1.1.6 里面我们从框架层面让websocket 的支持落地...
    99+
    2022-06-07
    GO chat websocket
  • 怎么使用Android快速实现一个财务APP程序
    这篇文章主要介绍了怎么使用Android快速实现一个财务APP程序的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么使用Android快速实现一个财务APP程序文章都会有所收获,下面我们一起来看看吧。一,系统的...
    99+
    2023-07-02
  • Go快速开发一个RESTfulAPI服务
    目录何时使用单体 RESTful 服务商城单体 RESTful 服务单体服务实现Mall API 定义账号模块 API 定义订单模块 API 定义商品模块 API 定义生成单体服务实...
    99+
    2024-04-02
  • 怎么使用JavaScript快速实现一个颜色选择器
    本文小编为大家详细介绍“怎么使用JavaScript快速实现一个颜色选择器”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么使用JavaScript快速实现一个颜色选择器”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知...
    99+
    2023-07-05
  • 怎么在HTML5中使用WebSocket实现一个聊天室
    本篇文章给大家分享的是有关怎么在HTML5中使用WebSocket实现一个聊天室,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1)注册注册要处理几个事情,分别是注册完成后获取当...
    99+
    2023-06-09
  • 利用Go语言快速实现一个极简任务调度系统
    目录引子思路实战交互界面定时任务任务执行代码效果总结引子 任务调度(Task Scheduling)是很多软件系统中的重要组成部分,字面上的意思是按照一定要求分配运行一些通常时间较长...
    99+
    2024-04-02
  • 怎么在Android中使用WebSocket实现一个多人游戏
    今天就跟大家聊聊有关怎么在Android中使用WebSocket实现一个多人游戏,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。webSocket流程客户端开始连接------->...
    99+
    2023-05-30
    android websocket
  • Go Http Server框架怎么快速实现?一文搞定
    本篇文章给大家介绍有关Golang的相关知识,聊聊Go Http Server框架的怎么快速实现的,希望对大家有所帮助。在Go想使用 http server,最简单的方法是使用 http/neterr := http.ListenAndSe...
    99+
    2023-05-14
    Golang
  • python中怎么实现一个快速支付接口
    今天就跟大家聊聊有关python中怎么实现一个快速支付接口,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。首先定义数据如下:#用的测试平台的数据data=[  &n...
    99+
    2023-06-17
  • go快速排序算法怎么实现
    快速排序(Quick Sort)是一种高效的排序算法,它的基本思想是选择一个基准元素,通过一趟排序将数组分成两部分,其中一部分的所有...
    99+
    2023-10-26
    go
  • 使用JAVA怎么快速搭建一个springboot项目
    今天就跟大家聊聊有关使用JAVA怎么快速搭建一个springboot项目,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。安装JDK使用的是jdk8,这里使用的是windows10 64...
    99+
    2023-06-06
  • 在Java中怎么实现一个快速排序算法
    在Java中怎么实现一个快速排序算法?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。快速排序的原理:选择一个关键值作为基准值。比基准值小的都在左边序列(一般是无序...
    99+
    2023-05-30
    java
  • 怎么在Android中利用RecyclerView实现一个快速滚动功能
    本篇文章给大家分享的是有关怎么在Android中利用RecyclerView实现一个快速滚动功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。首先,在 build.gradle...
    99+
    2023-05-30
    recyclerview android
  • Android快速实现一个财务APP程序详解
    目录前言一,系统的技术栈二,系统界面三,系统核心代码前言 昨天有个粉丝朋友也想学开发Web和小程序、安卓,问可以在大学学会吗? 在学校学到的东西真的有限: 在很多的高校,有一些教授是...
    99+
    2024-04-02
  • 使用golang怎么实现一个DNS服务器
    使用golang怎么实现一个DNS服务器?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。golang适合做什么golang可以做服务器端开发,但golang很适合做日志处理、...
    99+
    2023-06-14
  • 如何使用PHP快速搭建一个图片服务器
    PHP是一种被广泛应用于Web开发的服务器端脚本语言。在很多实际应用中,我们需要搭建一些服务器来专门存储和管理图片,以供我们的应用和网站进行引用和展示。本文介绍如何使用PHP快速搭建一个图片服务器。基础环境安装在开始之前,我们需要安装PHP...
    99+
    2023-05-14
  • 如何用MySQL快速实现一个推荐算法
    本文小编为大家详细介绍“如何用MySQL快速实现一个推荐算法”,内容详细,步骤清晰,细节处理妥当,希望这篇“如何用MySQL快速实现一个推荐算法”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学...
    99+
    2023-01-31
    mysql
  • 怎么在Django中使用channels和websocket实现一个在线聊天室
    本篇文章为大家展示了怎么在Django中使用channels和websocket实现一个在线聊天室,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Channels是Django团队研发的一个给Djan...
    99+
    2023-06-15
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作