douqie1884 2016-03-22 13:19
浏览 53
已采纳

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

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.

communication flow between mobile phone and server.

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.

  • 写回答

2条回答 默认 最新

  • dongwuchu0314 2016-03-22 15:40
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?