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

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

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.

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:

确定