websocket发送/接收是否是线程安全的(去常规安全)?

时间:2012-06-11 19:03:52

标签: concurrency websocket go

在GO中编写websocket服务器时(在我的情况下使用JSON编解码器),有两个不同的Go例程来处理同一连接上的数据发送和接收是否安全?

由于websocket.JSON.Receive暂停并等待接收数据,我认为处理数据发送的单独Go例程将是一个有效的解决方案,除非在同一连接上无法同时发送/接收。

那么,下面的工作示例是不良做法吗?

package main

import (
    "fmt"
    "net/http"
    "code.google.com/p/go.net/websocket"
)

const queueSize = 20

type Input struct {
    Cmd    string
}

type Output struct {
    Cmd    string
}

func Handler(ws *websocket.Conn) {

    msgWrite := make(chan *Output, queueSize)
    var in Input

    go writeHandler(ws, msgWrite)

    for {

        err := websocket.JSON.Receive(ws, &in)

        if err != nil {
            fmt.Println(err)
            break
        } else {
            msgWrite <- &Output{Cmd: "Thanks for your message: " + in.Cmd}
        }
    }
}

func writeHandler(ws *websocket.Conn, out chan *Output) {
    var d *Output
    for {
        select {
        case d = <-out:
            if err := websocket.JSON.Send(ws, &d); err != nil {
                fmt.Println(err.Error())
            } else {
                fmt.Println("> ", d.Cmd)
            }
        }
    }
}

func main() {
    http.Handle("/echo", websocket.Handler(Handler));
    err := http.ListenAndServe(":1235", nil);
    if err != nil {
        panic("ListenAndServe: " + err.Error())
    }
    fmt.Println("Server running")
}

2 个答案:

答案 0 :(得分:9)

是的,您可以同时在websocket连接上调用Send,Receive和Close,就像Go中的所有net.Conn一样。官方文档的简短摘录:

  

多个goroutine可以同时调用Conn上的方法。

此外,websocket包还引入了一些编解码器,用于发送/写入可能原子占用多个帧的消息或JSON数据。如果查看源代码,可以看到Codec类型的Send and Receive方法将包含读锁定或写锁定。

答案 1 :(得分:1)

引自http://www.gorillatoolkit.org/pkg/websocket

并发

Connections支持一个并发读者和一个并发编写器。

应用程序负责确保不超过一个goroutine同时调用write方法(NextWriter,SetWriteDeadline,WriteMessage,WriteJSON,EnableWriteCompression,SetCompressionLevel),并且只有一个goroutine调用read方法(NextReader,SetReadDeadline,ReadMessage,同时使用ReadJSON,SetPongHandler,SetPingHandler。

可以与所有其他方法同时调用Close和WriteControl方法。