我是Go的新手,作为我的第一个测试项目之一,我想编写一个使用UDP的简单客户端/服务器程序。我已经让它工作了,但有很多方法可以做到这一点,我想知道哪种方式最好。
net.Listen()与net.ListenUDP()与net.ListenPacket()之间的区别
net.Read()与net.ReadFrom()与net.ReadFromUDP()之间的区别
net.Write()与net.WriteTo()与net.WriteToUDP()之间的区别
我是Go的新手,作为我的第一个测试项目之一,我想编写一个使用UDP的简单客户端/服务器程序。我已经让它工作了,但有很多方法可以做到这一点,我想知道哪种方式最好。
net.Listen()与net.ListenUDP()与net.ListenPacket()之间的区别
net.Read()与net.ReadFrom()与net.ReadFromUDP()之间的区别
net.Write()与net.WriteTo()与net.WriteToUDP()之间的区别
让我们来看看你的问题。
net.Listen()、net.ListenUDP()和net.ListenPacket()有何区别?
Listen在本地网络地址laddr上进行通信。网络net必须是面向流的网络:"tcp","tcp4","tcp6","unix"或"unixpacket"。有关laddr的语法,请参见Dial。
使用示例#1:
tcpSock, err := net.Listen("tcp", "0.0.0.0:8080")
使用示例 #2
unixSock, err := net.Listen("unix", "/var/app/server.sock")
net.Listen()
作为一个开关语句,调用了net.ListenTCP
或者net.ListenUnix
,否则就会抛出默认错误。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()文档以获取更多信息。
因此,我们可以从最初的比较中排除net.ListenUDP
;并查看net.ListenPacket()
。
ListenPacket在本地网络地址laddr上进行通告。网络net必须是面向数据包的网络:"udp"、"udp4"、"udp6"、"ip"、"ip4"、"ip6"或"unixgram"。有关laddr的语法,请参见Dial。
使用示例 #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
}
这些函数通常用于从不同的net
连接中读取数据。
Read()
函数都来自实现了Conn
接口的类型。
Conn接口定义如下:
……一个通用的面向流的网络连接。
为了实现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
}
因此,这应该清楚地表明实际上没有net.Read()
;而是操作实现了net.Conn
接口的类型的Read()
函数。
PacketConn是一种通用的面向数据包的网络连接。
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
}
正如你所猜测的那样,我们一遍又一遍地看着相同的模式。这被称为实现接口。我会让你根据上面的解释自己查找这个特定方法以及它是如何工作的。
你最好先看一下 Effective Go 关于接口的部分。
net.ListenUDP()
、net.ReadFromUDP()
等函数。 - trent
net.Listen()
)适用于各种连接,但它们不公开UDP特定功能。如果您想执行特定于UDP的操作,请使用ListenUDP()
。 - fuz