我是Go的新手,并且发现自己作为第一个项目使用套接字。这是一个多余的问题,但我未能理解 将网络套接字更新发送到Go中的特定客户端(使用Gorilla)。
我要解决的主要问题是-使用websocket和搜索引擎(如ES / Lucene)构建预输入。我在搜索引擎上维护了一堆索引,并且周围有一个Go包装器。当我开始在Go中使用websockets时,几乎发现了所有展示广播机制的示例。当我尝试对此进行深入研究并尝试根据repo线程和此this中给出的示例修改Gorilla的github answer中给出的示例时,我似乎不太明白connections
以及它如何适合client.go
理想情况下,我希望看到此工作的方式是-
服务器如何唯一标识Client
?
我使用了大猩猩的Github repo
上给出的示例在我的代码库hub.go
中,以下内容
type Hub struct {
// Registered clients.
clients map[*Client]bool
// Inbound messages from the clients.
broadcast chan []byte
// Register requests from the clients.
register chan *Client
// Unregister requests from clients.
unregister chan *Client
connections map[string]*connection
}
func newHub() *Hub {
return &Hub{
broadcast: make(chan []byte),
register: make(chan *Client),
unregister: make(chan *Client),
clients: make(map[*Client]bool),
connection: make(map[*Client]bool), // is this alright?
}
}
func (h *Hub) run() {
for {
select {
case client := <-h.register:
h.clients[client] = true
case client := <-h.unregister:
if _, ok := h.clients[client]; ok {
delete(h.clients, client)
close(client.send)
}
case message := <-h.broadcast:
for client := range h.connections {
select {
case client.send <- message:
default:
close(client.send)
delete(h.connections, client)
}
}
}
}
}
我不确定应该添加到client.go
type Client struct {
// unique ID for each client
// id string
// Hub object
hub *Hub
// The websocket connection.
conn *websocket.Conn
// Buffered channel of outbound messages.
send chan []byte
// connection --> (what should the connection property be?)
connection string
}
请注意-我将在Id
结构内添加一个Client
字段。我怎么从这里开始?
答案 0 :(得分:1)
聊天示例显示了如何实现广播。如果不需要广播,则聊天示例不是应用程序的理想起点。
要将消息发送到特定的Websocket连接,只需使用NextWriter或WriteMessage写入该连接即可。这些方法不支持并发编写器,因此您可能需要使用互斥量或goroutine来确保单个编写器。
查找特定*websocket.Connection
的简单方法是将*websocket.Connection
传递给需要它的代码。如果应用程序需要将其他状态与连接相关联,则定义一个类型以保留该状态并在其周围传递一个指针:
type Client struct {
conn *websocket.Conn
mu sync.Mutex
...
}
可以Hub
进行修改以将消息发送到特定的连接,但是如果不需要广播,则这是环岛路径。操作方法如下:
向客户添加ID字段:
ID idType // replace idType with int, string, or whatever you want to use
将Gorilla集线器字段从connections map[*connection]bool
更改为connections map[idType]*connection
。
定义包含消息数据和目标客户端ID的消息类型:
type message struct {
idType ID
data []byte
}
将中心广播字段替换为:
send chan message
将循环中心更改为:
for {
select {
case client := <-h.register:
h.clients[client.ID] = client
case client := <-h.unregister:
if _, ok := h.clients[client.ID]; ok {
delete(h.clients, client.ID)
close(client.send)
}
case message := <-h.send:
if client, ok := h.clients[message.ID]; ok {
select {
case client.send <- message.data:
default:
close(client.send)
delete(h.connections, client)
}
}
}
通过创建具有适当ID的message
将消息发送到特定客户端:
hub.send <- message{ID: targetID, data: data}