golang net.UDPConn 和 net.TCPConn 线程安全吗?我可以在多线程中读取或写入单个 UDPConn 对象吗?
Are golang net.UDPConn and net.TCPConn thread safe?? Can i read or write of single UDPConn object in multi thread?
1.Can 我们在同一个 net.UDPConn 或 net.TCPConn 对象上从一个线程调用发送并从另一个线程调用接收?
2.Can 我们在同一个 net.UDPConn 或 net.TCPConn 对象上从不同线程并行调用多个发送?
我也找不到同样的好文档。
golang socket api线程安全吗?
我发现很难测试它是否是线程安全的。
方向上的任何指示都会有所帮助。
我的测试代码如下:
package main
import (
"fmt"
"net"
"sync"
)
func udp_server() {
// create listen
conn, err := net.ListenUDP("udp", &net.UDPAddr{
IP: net.IPv4(0, 0, 0, 0),
Port: 8080,
})
if err != nil {
fmt.Println("listen fail", err)
return
}
defer conn.Close()
var wg sync.WaitGroup
for i := 0; i < 10; i = i + 1 {
wg.Add(1)
go func(socket *net.UDPConn) {
defer wg.Done()
for {
// read data
data := make([]byte, 4096)
read, remoteAddr, err := socket.ReadFromUDP(data)
if err != nil {
fmt.Println("read data fail!", err)
continue
}
fmt.Println(read, remoteAddr)
fmt.Printf("%s\n\n", data)
// send data
senddata := []byte("hello client!")
_, err = socket.WriteToUDP(senddata, remoteAddr)
if err != nil {
return
fmt.Println("send data fail!", err)
}
}
}(conn)
}
wg.Wait()
}
func main() {
udp_server()
}
这个测试码可以吗?
net.Conn
的文档说:
Multiple goroutines may invoke methods on a Conn simultaneously.
Multiple goroutines may invoke methods on a Conn simultaneously.
我对上面文档的解释是,如果您从多个 go 例程中对 net.Conn
调用 Read
和 Write
,并且调用 [=来自多个 go 例程的 net.Conn
上的 12=] 将被序列化,以便来自对 Write
的 2 个单独调用的字节在写入网络时不会交错。
您提供的代码的问题在于无法保证 Write
会一次性写入提供给它的整个字节片。您忽略了已写入多少字节的指示。
_, err = socket.WriteToUDP(senddata, remoteAddr)
因此,为了确保您编写了循环调用 Write
所需的所有内容,直到所有 senddata
都已发送。但是 net.Conn
只能确保来自对 Write 的 单次 调用的数据不会交错。鉴于您可以通过多次写入调用发送单个数据块,因此无法保证单个数据块将完好无损地到达目的地。
因此,例如 3 "hello client!" 条消息可能会以以下形式到达。
"hellohellohello client! client! client!"
因此,如果您希望通过多个 go 例程在 net.Conn
上写入可靠的消息,您将需要同步这些例程以确保完整地写入单个消息。
如果我想这样做,作为第一次尝试,我会有一个从一个或多个消息通道读取并写入 net.Conn
的单个 go 例程,然后多个 go 例程可以写入这些消息通道.
1.Can 我们在同一个 net.UDPConn 或 net.TCPConn 对象上从一个线程调用发送并从另一个线程调用接收?
2.Can 我们在同一个 net.UDPConn 或 net.TCPConn 对象上从不同线程并行调用多个发送?
我也找不到同样的好文档。 golang socket api线程安全吗?
我发现很难测试它是否是线程安全的。 方向上的任何指示都会有所帮助。
我的测试代码如下:
package main
import (
"fmt"
"net"
"sync"
)
func udp_server() {
// create listen
conn, err := net.ListenUDP("udp", &net.UDPAddr{
IP: net.IPv4(0, 0, 0, 0),
Port: 8080,
})
if err != nil {
fmt.Println("listen fail", err)
return
}
defer conn.Close()
var wg sync.WaitGroup
for i := 0; i < 10; i = i + 1 {
wg.Add(1)
go func(socket *net.UDPConn) {
defer wg.Done()
for {
// read data
data := make([]byte, 4096)
read, remoteAddr, err := socket.ReadFromUDP(data)
if err != nil {
fmt.Println("read data fail!", err)
continue
}
fmt.Println(read, remoteAddr)
fmt.Printf("%s\n\n", data)
// send data
senddata := []byte("hello client!")
_, err = socket.WriteToUDP(senddata, remoteAddr)
if err != nil {
return
fmt.Println("send data fail!", err)
}
}
}(conn)
}
wg.Wait()
}
func main() {
udp_server()
}
这个测试码可以吗?
net.Conn
的文档说:
Multiple goroutines may invoke methods on a Conn simultaneously.
Multiple goroutines may invoke methods on a Conn simultaneously.
我对上面文档的解释是,如果您从多个 go 例程中对 net.Conn
调用 Read
和 Write
,并且调用 [=来自多个 go 例程的 net.Conn
上的 12=] 将被序列化,以便来自对 Write
的 2 个单独调用的字节在写入网络时不会交错。
您提供的代码的问题在于无法保证 Write
会一次性写入提供给它的整个字节片。您忽略了已写入多少字节的指示。
_, err = socket.WriteToUDP(senddata, remoteAddr)
因此,为了确保您编写了循环调用 Write
所需的所有内容,直到所有 senddata
都已发送。但是 net.Conn
只能确保来自对 Write 的 单次 调用的数据不会交错。鉴于您可以通过多次写入调用发送单个数据块,因此无法保证单个数据块将完好无损地到达目的地。
因此,例如 3 "hello client!" 条消息可能会以以下形式到达。
"hellohellohello client! client! client!"
因此,如果您希望通过多个 go 例程在 net.Conn
上写入可靠的消息,您将需要同步这些例程以确保完整地写入单个消息。
如果我想这样做,作为第一次尝试,我会有一个从一个或多个消息通道读取并写入 net.Conn
的单个 go 例程,然后多个 go 例程可以写入这些消息通道.