英文:
concurrent relaying of data between multiple clients
问题
我目前正在开发一个应用程序,通过服务器将手机发送的数据传输到浏览器,使用的是WebSockets。我正在使用Go语言编写服务器,并且手机和浏览器之间是一对一的关系,如下图所示。
然而,我希望能够同时处理多个会话。
我了解到Go语言提供了并发模型,遵循"通过通信共享内存"的原则,使用goroutines和channels。我更倾向于使用这个原则,而不是使用sync.Mutex
原语来进行锁操作。
然而,我还没有找到如何将这个信息应用到我的问题上,所以我想问你是否能够提供一个解决方案。
英文:
I am currently working on an application relaying data sent from a mobile phone via a server to a browser using WebSockets. I am writing the server in go and I have a one-to-one relation between the mobile phones and the browsers as shown by the following illustration.
However, I want multiple sessions to work simultaneously.
I have read that go provides concurrency models that follow the principle "share memory by communicating" using goroutines and channels. I would prefer using the mentioned principle rather than locks using the sync.Mutex
primitive.
Nevertheless, I have not been able to map this information to my issue and wanted to ask you if you could suggest a solution.
答案1
得分: 2
我遇到了一个类似于你的问题,我需要多个连接,每个连接通过多个服务器相互发送数据。
我选择了WAMP协议。
WAMP是一个开放的标准WebSocket子协议,提供了两种应用消息传递模式:
远程过程调用 + 发布和订阅。
你还可以看一下我的一个项目,它使用go语言编写,并使用了这个协议:github.com/neutrinoapp/neutrino
英文:
I had a similar to your problem, I needed multiple connections which each send data to each other through multiple servers.
I went with the WAMP protocol
WAMP is an open standard WebSocket subprotocol that provides two application messaging patterns in one unified protocol:
Remote Procedure Calls + Publish & Subscribe.
You can also take a look at a project of mine which is written in go and uses the protocol at hand: github.com/neutrinoapp/neutrino
答案2
得分: 1
在Go语言中使用互斥锁是没有问题的。以下是使用互斥锁的解决方案。
首先声明一个端点的映射。我假设一个字符串键足以标识一个端点:
type endpoint struct {
c *websocket.Conn
sync.Mutex // 保护对c的写操作
}
var (
endpoints = map[string]*endpoint
endpointsMu sync.Mutex // 保护endpoints
)
func addEndpoint(key string, c *websocket.Connection) {
endpointsMu.Lock()
endpoints[key] = &endpoint{c:c}
endpointsMu.Unlock()
}
func removeEndpoint(key string) {
endpointsMu.Lock()
delete(endpoints, key)
endpointsMu.Unlock()
}
func sendToEndpoint(key string, message []byte) error {
endpointsMu.Lock()
e := endpoints[key]
endpointsMu.Unlock()
if e == nil {
return errors.New("no endpoint")
}
e.Lock()
defer e.Unlock()
return e.c.WriteMessage(websocket.TextMessage, message)
}
当客户端连接时,使用addEndpoint
将连接添加到映射中。当关闭连接时,使用removeEndpoint
从映射中移除连接。使用sendToEndpoint
向指定的端点发送消息。
可以根据需要修改Gorilla聊天示例来解决这个问题。将hub
映射更改为connections map[string]*connection
,更新通道以发送带有连接和键的类型,并将广播循环更改为向单个连接发送消息。
英文:
There's nothing wrong with using a mutex in Go. Here's a solution using a mutex.
Declare a map of endpoints. I assume that a string key is sufficient to identify an endpoint:
type endpoint struct {
c *websocket.Conn
sync.Mutex // protects write to c
}
var (
endpoints = map[string]*endpoint
endpointsMu sync.Mutex // protects endpoints
)
func addEndpoint(key string, c *websocket.Connection) {
endpointsMu.Lock()
endpoints[key] = &endpoint{c:c}
endpointsMu.Unlock()
}
func removeEndpoint(key string) {
endpointsMu.Lock()
delete(endpoints, key)
endpointsMu.Unlock()
}
func sendToEndpoint(key string, message []byte) error {
endpointsMu.Lock()
e := endpoints[key]
endpointsMu.Unlock()
if e === nil {
return errors.New("no endpoint")
}
e.Lock()
defer e.Unlock()
return e.c.WriteMessage(websocket.TextMessage, message)
}
Add the connection to the map with addEndpoint
when the client connects. Remove the connection from the map with removeEndpoint
when closing the connection. Send messages to a named endpoint with sendToEndpoint
.
The Gorilla chat example can be adapted to solve this problem. Change the hub map to connections map[string]*connection
, update channels to send a type with connection and key and change the broadcast loop to send to a single connection.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论