【问题标题】:Are golang net.UDPConn and net.TCPConn thread safe?? Can i read or write of single UDPConn object in multi thread?golang net.UDPConn 和 net.TCPConn 线程安全吗?我可以在多线程中读取或写入单个 UDPConn 对象吗?
【发布时间】:2015-04-18 23:46:14
【问题描述】:

1.我们能否在同一个 net.UDPConn 或 net.TCPConn 对象上从一个线程调用 send 并从另一个线程调用 recv?

2.我们可以从同一个 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()
}

这个测试代码可以吗?

【问题讨论】:

    标签: sockets go thread-safety


    【解决方案1】:

    net.Conn 的文档说:

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

    【讨论】:

      【解决方案2】:

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

      我对上述文档的解释是,如果您在多个 go 例程中调用 net.Conn 上的 ReadWrite,并且从多个 go 例程中调用 Write go 例程将被序列化,以便来自 2 个单独调用 Write 的字节在写入网络时不会被交错。

      您提供的代码的问题是不能保证Write 会一次性写入提供给它的整个字节片。您忽略了已写入多少字节的指示。

      _, err = socket.WriteToUDP(senddata, remoteAddr)
      

      因此,为了确保您编写了循环所需的所有内容并调用Write,直到所有senddata 发送完毕。但net.Conn 仅确保来自single 调用Write 的数据不会交错。鉴于您可以通过多次调用 write 发送单个数据块,因此无法保证单个数据块会完整地到达其目的地。

      例如 3 “你好客户!”消息可能以下列形式到达。

      “hellohellohello客户端!客户端!客户端!”

      因此,如果您希望通过多个 go 例程在 net.Conn 上可靠地写入消息,则需要同步这些例程以确保单个消息被完整写入。

      如果我想这样做,作为第一次尝试,我将有一个 goroutine 从一个或多个消息通道读取并写入net.Conn,然后多个 go 例程可以写入这些消息通道。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-29
        相关资源
        最近更新 更多