多个客户端之间的并发中继数据

huangapple go评论109阅读模式
英文:

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协议。

  1. WAMP是一个开放的标准WebSocket子协议,提供了两种应用消息传递模式:
  2. 远程过程调用 + 发布和订阅。

你还可以看一下我的一个项目,它使用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

  1. WAMP is an open standard WebSocket subprotocol that provides two application messaging patterns in one unified protocol:
  2. 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语言中使用互斥锁是没有问题的。以下是使用互斥锁的解决方案。

首先声明一个端点的映射。我假设一个字符串键足以标识一个端点:

  1. type endpoint struct {
  2. c *websocket.Conn
  3. sync.Mutex // 保护对c的写操作
  4. }
  5. var (
  6. endpoints = map[string]*endpoint
  7. endpointsMu sync.Mutex // 保护endpoints
  8. )
  9. func addEndpoint(key string, c *websocket.Connection) {
  10. endpointsMu.Lock()
  11. endpoints[key] = &endpoint{c:c}
  12. endpointsMu.Unlock()
  13. }
  14. func removeEndpoint(key string) {
  15. endpointsMu.Lock()
  16. delete(endpoints, key)
  17. endpointsMu.Unlock()
  18. }
  19. func sendToEndpoint(key string, message []byte) error {
  20. endpointsMu.Lock()
  21. e := endpoints[key]
  22. endpointsMu.Unlock()
  23. if e == nil {
  24. return errors.New("no endpoint")
  25. }
  26. e.Lock()
  27. defer e.Unlock()
  28. return e.c.WriteMessage(websocket.TextMessage, message)
  29. }

当客户端连接时,使用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:

  1. type endpoint struct {
  2. c *websocket.Conn
  3. sync.Mutex // protects write to c
  4. }
  5. var (
  6. endpoints = map[string]*endpoint
  7. endpointsMu sync.Mutex // protects endpoints
  8. )
  9. func addEndpoint(key string, c *websocket.Connection) {
  10. endpointsMu.Lock()
  11. endpoints[key] = &endpoint{c:c}
  12. endpointsMu.Unlock()
  13. }
  14. func removeEndpoint(key string) {
  15. endpointsMu.Lock()
  16. delete(endpoints, key)
  17. endpointsMu.Unlock()
  18. }
  19. func sendToEndpoint(key string, message []byte) error {
  20. endpointsMu.Lock()
  21. e := endpoints[key]
  22. endpointsMu.Unlock()
  23. if e === nil {
  24. return errors.New("no endpoint")
  25. }
  26. e.Lock()
  27. defer e.Unlock()
  28. return e.c.WriteMessage(websocket.TextMessage, message)
  29. }

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.

huangapple
  • 本文由 发表于 2016年3月22日 21:19:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/36155486.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定