英文:
Is websocket Send/Receive thread-safe (go routine-safe)?
问题
当在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")
}
英文:
When writing a websocket server in GO (in my case using the JSON codec), is it safe to have two different Go routines for handling sending and receiving of data on the same connection?
Since websocket.JSON.Receive
pauses and waits to receive data, I thought a separate Go routine for handling sending of data would be a working solution unless concurrent sending/receiving is not possible on the same connection.
So, is the working example below bad practice?
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")
}
答案1
得分: 13
是的,您可以同时在websocket连接上调用Send、Receive和Close,就像在Go中可以使用所有net.Conn一样。以下是官方文档的一小段摘录:
> 多个goroutine可以同时调用Conn上的方法。
此外,websocket包还引入了一些编解码器,用于原子地发送/写入消息或JSON数据,这些数据可能占用多个帧。如果您查看源代码,可以看到Codec类型的Send和Receive方法将保持读取或写入锁定。
英文:
Yes, you can call Send, Receive and Close on a websocket connection concurrently, like you can with all net.Conn's in Go. A short excerpt from the official docs:
> Multiple goroutines may invoke methods on a Conn simultaneously.
Additionally, the websocket package also introduces some Codecs for sending / writing Messages or JSON data that might occupy multiple frames atomically. If you look at the source, you can see that the Send and Receive method of the Codec type will hold either the read or the write lock.
答案2
得分: 1
并发
连接支持一个并发的读取器和一个并发的写入器。
应用程序负责确保不超过一个goroutine同时调用写入方法(NextWriter,SetWriteDeadline,WriteMessage,WriteJSON,EnableWriteCompression,SetCompressionLevel),并且不超过一个goroutine同时调用读取方法(NextReader,SetReadDeadline,ReadMessage,ReadJSON,SetPongHandler,SetPingHandler)。
Close和WriteControl方法可以与所有其他方法同时调用。
英文:
Quoted from http://www.gorillatoolkit.org/pkg/websocket
Concurrency
Connections support one concurrent reader and one concurrent writer.
Applications are responsible for ensuring that no more than one goroutine calls the write methods (NextWriter, SetWriteDeadline, WriteMessage, WriteJSON, EnableWriteCompression, SetCompressionLevel) concurrently and that no more than one goroutine calls the read methods (NextReader, SetReadDeadline, ReadMessage, ReadJSON, SetPongHandler, SetPingHandler) concurrently.
The Close and WriteControl methods can be called concurrently with all other methods.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论