go - net包中listen、read和write函数的区别

标签 go

我是 Go 新手,作为我的第一个测试项目之一,我想编写一个使用 UDP 的简单客户端/服务器程序。我让它工作了,但是有很多方法可以做到,我想知道哪种方法最好。

net.Listen() vs net.ListenUDP() vs net.ListenPacket()

net.Read() vs net.ReadFrom() vs net.ReadFromUDP()

net.Write() vs net.WriteTo() vs net.WriteToUDP()

最佳答案

让我们检查您的问题。

1。 net.Listen() 与 net.ListenUDP() 与 net.ListenPacket()

net.Listen()

Listen announces on the local network address laddr. The network net must be a stream-oriented network: "tcp", "tcp4", "tcp6", "unix" or "unixpacket". See Dial for the syntax of laddr.

用法示例#1:

tcpSock, err := net.Listen("tcp", "0.0.0.0:8080")

用法示例#2

unixSock, err := net.Listen("unix", "/var/app/server.sock")

我们可以看到in the source net.Listen() 用作调用 net.ListenTCPnet.ListenUnix 或默认错误的 switch 语句:

func Listen(net, laddr string) (Listener, error) {
    la, err := resolveAddr("listen", net, laddr, noDeadline)
    if err != nil {
        return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
    }
    var l Listener
    switch la := la.toAddr().(type) {
    case *TCPAddr:
        l, err = ListenTCP(net, la)
    case *UnixAddr:
        l, err = ListenUnix(net, la)
    default:
        return nil, &OpError{
            Op:   "listen",
            Net:  net,
            Addr: la,
            Err:  &AddrError{Err: "unexpected address type", Addr: laddr},
        }
    }
    if err != nil {
        return nil, err // l is non-nil interface containing nil pointer
    }
    return l, nil
}

更多信息请访问 net.Listen() Docs

那么,我们可以从初始比较中消除net.ListenUDP;并查看 net.ListenPacket().

net.ListenPacket()

ListenPacket announces on the local network address laddr. The network net must be a packet-oriented network: "udp", "udp4", "udp6", "ip", "ip4", "ip6" or "unixgram". See Dial for the syntax of laddr.

用法示例#1:

pListener, err := net.ListenPacket("ip4", "0.0.0.0:9090")

而且,如果我们深入了解一下,我们可以看到它的运行方式与 net.Listen() 大致相同:

func ListenPacket(net, laddr string) (PacketConn, error) {
    la, err := resolveAddr("listen", net, laddr, noDeadline)
    if err != nil {
        return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
    }
    var l PacketConn
    switch la := la.toAddr().(type) {
    case *UDPAddr:
        l, err = ListenUDP(net, la)
    case *IPAddr:
        l, err = ListenIP(net, la)
    case *UnixAddr:
        l, err = ListenUnixgram(net, la)
    default:
        return nil, &OpError{
            Op:   "listen",
            Net:  net,
            Addr: la,
            Err:  &AddrError{Err: "unexpected address type", Addr: laddr},
        }
    }
    if err != nil {
        return nil, err // l is non-nil interface containing nil pointer
    }
    return l, nil
}

2。 net.Read() 与 net.ReadFrom() 与 net.ReadFromUDP()

如您所料,这些函数用于读取各种 net 连接。

net.Read()

如果您查看 net 包 - 您可以看到所有 Read() 函数都来自实现 Conn 接口(interface)的类型。

Conn接口(interface)定义为:

... a generic stream-oriented network connection.

为了实现net.Conn,你需要有以下方法:

type Conn interface {
    // Read reads data from the connection.
    // Read can be made to time out and return a Error with Timeout() == true
    // after a fixed time limit; see SetDeadline and SetReadDeadline.
    Read(b []byte) (n int, err error)

    // Write writes data to the connection.
    // Write can be made to time out and return a Error with Timeout() == true
    // after a fixed time limit; see SetDeadline and SetWriteDeadline.
    Write(b []byte) (n int, err error)

    // Close closes the connection.
    // Any blocked Read or Write operations will be unblocked and return errors.
    Close() error

    // LocalAddr returns the local network address.
    LocalAddr() Addr

    // RemoteAddr returns the remote network address.
    RemoteAddr() Addr

    // SetDeadline sets the read and write deadlines associated
    // with the connection. It is equivalent to calling both
    // SetReadDeadline and SetWriteDeadline.
    //
    // A deadline is an absolute time after which I/O operations
    // fail with a timeout (see type Error) instead of
    // blocking. The deadline applies to all future I/O, not just
    // the immediately following call to Read or Write.
    //
    // An idle timeout can be implemented by repeatedly extending
    // the deadline after successful Read or Write calls.
    //
    // A zero value for t means I/O operations will not time out.
    SetDeadline(t time.Time) error

    // SetReadDeadline sets the deadline for future Read calls.
    // A zero value for t means Read will not time out.
    SetReadDeadline(t time.Time) error

    // SetWriteDeadline sets the deadline for future Write calls.
    // Even if write times out, it may return n > 0, indicating that
    // some of the data was successfully written.
    // A zero value for t means Write will not time out.
    SetWriteDeadline(t time.Time) error
}

Source code

所以,这应该清楚地表明实际上没有 net.Read();而是对实现 net.Conn 接口(interface)的类型进行操作的 Read() 函数。

net.ReadFrom()

就像 net.Read() 一样,所有的实现都来自于实现一个接口(interface)。在这种情况下,该接口(interface)是 net.PacketConn

PacketConn is a generic packet-oriented network connection.

type PacketConn interface {
    // ReadFrom reads a packet from the connection,
    // copying the payload into b.  It returns the number of
    // bytes copied into b and the return address that
    // was on the packet.
    // ReadFrom can be made to time out and return
    // an error with Timeout() == true after a fixed time limit;
    // see SetDeadline and SetReadDeadline.
    ReadFrom(b []byte) (n int, addr Addr, err error)

    // WriteTo writes a packet with payload b to addr.
    // WriteTo can be made to time out and return
    // an error with Timeout() == true after a fixed time limit;
    // see SetDeadline and SetWriteDeadline.
    // On packet-oriented connections, write timeouts are rare.
    WriteTo(b []byte, addr Addr) (n int, err error)

    // Close closes the connection.
    // Any blocked ReadFrom or WriteTo operations will be unblocked
    // and return errors.
    Close() error

    // LocalAddr returns the local network address.
    LocalAddr() Addr

    // SetDeadline sets the read and write deadlines associated
    // with the connection.
    SetDeadline(t time.Time) error

    // SetReadDeadline sets the deadline for future Read calls.
    // If the deadline is reached, Read will fail with a timeout
    // (see type Error) instead of blocking.
    // A zero value for t means Read will not time out.
    SetReadDeadline(t time.Time) error

    // SetWriteDeadline sets the deadline for future Write calls.
    // If the deadline is reached, Write will fail with a timeout
    // (see type Error) instead of blocking.
    // A zero value for t means Write will not time out.
    // Even if write times out, it may return n > 0, indicating that
    // some of the data was successfully written.
    SetWriteDeadline(t time.Time) error
}

注意:TCPConn.ReadFrom来自于实现 io.ReaderFrom ReadFrom 方法。

3。 net.Write()

您可能已经猜到了,我们一遍又一遍地查看相同的模式。这称为实现接口(interface)。我将让您使用上述解释作为路线图来查找此特定方法及其工作原理。

你最好看看Effective Go parts about interfaces首先。

更多net包信息可在the source获得和 GoDoc

关于go - net包中listen、read和write函数的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24933352/

相关文章:

go - Golang 中 runtime.LockOSThread 的好处

mongodb - 定义ID int64时如何自动生成ID int64 `bson:“_id”`

go - vim-go、模块和 GoRename

go - 在 Go 的父目录中递归查找具有名称的文件

go - golang中的 bool 值没有异或运算符吗?

installation - 如何从下载源安装 golang 3rd-party 项目?

c# - 如何实现 Channels 的 BlockingCollection.TakeFromAny 等效项?

string - 戈朗 : bitwise operation on very long binary bit string representation

go - 获取日志文件中的结构字符串

c - Go 代码使用 getdents() 列出 Linux 目录中的文件