草庐IT

go - Websocket 发送到特定客户端而不是广播

coder 2023-06-27 原文

我正在尝试将 gorilla 聊天示例修改为向特定客户端发送消息而不是广播。首先,我根据它的 ID 将特定客户端存储在集线器中。

Hub.go

type Hub struct {
        Clients    map[int]*Client // Changed this piece to store id (int)
        Broadcast  chan []byte   
        Register   chan *Client   
        Unregister chan *Client   
}

func (h *Hub) Run() {
        for {
                    select {
                    case client := <-h.Register:
                                fmt.Println("hub client register")
                                h.Clients[client.Id] = client
                    case client := <-h.Unregister:
                                fmt.Println("hub client Unregister")
                                fmt.Println(h.Clients[client.Id])
                                if h.Clients[client.Id] != nil {
                                            delete(h.Clients, client.Id)
                                            close(client.Send)
                                }
                    case message := <-h.Broadcast:
                                fmt.Println("to send to a specific client", string(message))
                    }
        }
}

客户端

我在Client中添加了一个字段Id int来知道哪个客户端发送了消息

type Client struct {
        Hub  *Hub
        Conn *websocket.Conn
        Send chan []byte    
        Id   int // Id of the client,
}

func (c *Client) readPump() {
        defer func() {
                    c.Hub.Unregister <- c
                    c.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 {
                    _, message, err := c.Conn.ReadMessage()
                    if err != nil {
                                if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
                                            log.Printf("error: %v", err)
                                }
                                break
                    }
                    message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1))

                    fmt.Println("client read message", string(message), "from", c.Id)
        // {"to":512,"message":"Hi there."}
                    c.Hub.Broadcast <- message
        }
}

接下来要采取哪些步骤才能将消息发送到特定客户端而不是广播。

消息本身以 JSON 形式来自客户端,指定“收件人”以指示发送给谁以及发送什么消息。

{"to":512,"message":"Hi there."}

最佳答案

定义一个表示消息的类型:

type Message struct {
    id int
    data []byte
}

向 Hub 添加字段:

Send chan Message

并与集线器的其他 channel 一起初始化 channel 。

将以下情况添加到集线器的选择中:

case m := <-h.Send:
    c, ok := clients[m.id]
    if ok {
        select {
        case c.send <- m.data:
        default:
           delete(h.Clients, c.Id)
           close(c.Send)
        }
    }

在客户端的接收循环中,解析JSON得到id和message数据,发送给hub:

    c.Hub.Send <- Message{id: id, data: data}

关于go - Websocket 发送到特定客户端而不是广播,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43378283/

有关go - Websocket 发送到特定客户端而不是广播的更多相关文章

  1. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  2. 【Java 面试合集】HashMap中为什么引入红黑树,而不是AVL树呢 - 2

    HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候

  3. Ruby - 如何在读取文件时跳过/忽略特定行? - 2

    在读取/解析文件(使用Ruby)时忽略某些行的最佳方法是什么?我正在尝试仅解析Cucumber.feature文件中的场景,并希望跳过不以Scenario/Given/When/Then/And/But开头的行。下面的代码有效,但它很荒谬,所以我正在寻找一个聪明的解决方案:)File.open(file).each_linedo|line|line.chomp!nextifline.empty?nextifline.include?"#"nextifline.include?"Feature"nextifline.include?"Inorder"nextifline.include?

  4. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

    我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

  5. ruby - 未定义的方法 auto_upgrade!将 Sinatra/DataMapper 应用程序推送到 Heroku 时 - 2

    有谁知道在Heroku的Bamboo堆栈上启动并运行使用DataMapper的Sinatra应用程序所需的魔法咒语?Bamboo堆栈不包含任何预安装的系统gem,无论我尝试使用何种gem组合,我都会不断收到此错误:undefinedmethod`auto_upgrade!'forDataMapper:Module(NoMethodError)这是我的.gems文件中的内容:sinatrapgdatamapperdo_postgresdm-postgres-adapter这些是我将应用程序推送到Heroku时安装的依赖项:----->Herokureceivingpush----->Si

  6. ruby-on-rails - 只有当不是 nil 时才执行映射? - 2

    如果names为nil,则以下中断。我怎样才能让这个map只有在它不是nil时才执行?self.topics=names.split(",").mapdo|n|Topic.where(name:n.strip).first_or_create!end 最佳答案 其他几个选项:选项1(在其上执行map时检查split的结果):names_list=names.try(:split,",")self.topics=names_list.mapdo|n|Topic.where(name:n.strip).first_or_create!e

  7. ruby - Faye WebSocket,关闭处理程序被触发后重新连接到套接字 - 2

    我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d

  8. ruby-on-rails - Rails 格式验证——字母数字,但不是纯数字 - 2

    什么是测试格式验证的最佳方法让我们说一个用户名,使用字母数字的正则表达式,但不是纯数字?我一直在我的模型中使用以下验证validates:username,:format=>{:with=>/^[a-z0-9]+[-a-z0-9]*[a-z0-9]+$/i}数字用户名(例如“342”)通过了验证,这是我不想要的。 最佳答案 您想“向前看”一封信:/\A(?=.*[a-z])[a-z\d]+\Z/i 关于ruby-on-rails-Rails格式验证——字母数字,但不是纯数字,我们在Sta

  9. ruby - 强制浏览器下载文件而不是打开文件 - 2

    我要下载http://foobar.com/song.mp3作为song.mp3,而不是让Chrome在其native中打开它浏览器中的播放器。我怎样才能做到这一点? 最佳答案 您只需要确保发送这些header:Content-Disposition:attachment;filename=song.mp3;Content-Type:application/octet-streamContent-Transfer-Encoding:binarysend_file方法为您完成:get'/:file'do|file|file=File.

  10. ruby-on-rails - Ruby on Rails - 需要在每周的特定时间将消息发送到电子邮件 - 2

    我想知道我应该如何着手这个项目。我需要每周向人们发送一次电子邮件。但是,这必须在每周的特定时间自动生成并发送。编码有多难?我需要知道是否有任何书籍可以提供帮助,或者你们中的任何人是否可以指导我。它必须使用ruby​​onrails进行编程。因此有一个网络服务和数据库集成。干杯 最佳答案 为什么这么复杂?您只需安排工作。您可以使用Delayed::Job例如。Delayed::Job让您可以使用run_at符号在特定时间安排作业,如下所示:Delayed::Job.enqueue(SendEmailJob.new(...),:run_

随机推荐