今为止我们已经区分TCP和UDP API的不同,使用例子DialTCP和DialUDP分别返回一个TCPConn和 UDPConn。Conn类型是一个接口,TCPConn和UDPConn实现了该接口。在很大程度上,你可以通过该接口处理而不是用这两种类型。
Dialnetwork, address string) Conn, error)
net可以是”tcp”, “tcp4” IPv4-only), “tcp6” IPv6-only), “udp”, “udp4” IPv4-only), “udp6” IPv6-only), “ip”, “ip4″ IPv4-only)和”ip6” IPv6-only)任何一种。它将返回一个实现了Conn接口的类型。注意此函数接受一个字符串而不是raddr地址参数,因此,使用此程序可避免的地址类型。
使用该函数需要对程序轻微的调整。例如, 前面的程序从一个Web页面获取HEAD信息可以被重新写为
一个客户端的例子
package main import "bytes" "fmt" "io" "net" "os" ) func main) { if lenos.Args) != 2 { fmt.Fprintfos.Stderr, "Usage: %s host:port", os.Args[0]) os.Exit1) } service := os.Args[1] conn, err := net.Dial"tcp", service) checkErrorerr) _, err = conn.Write[]byte"HEAD / HTTP/1.0\r\n\r\n")) checkErrorerr) result, err := readFullyconn) checkErrorerr) fmt.Printlnstringresult)) os.Exit0) } func checkErrorerr error) { if err != nil { fmt.Fprintfos.Stderr, "Fatal error: %s", err.Error)) os.Exit1) } } func readFullyconn net.Conn) []byte, error) { defer conn.Close) result := bytes.NewBuffernil) var buf [512]byte for { n, err := conn.Readbuf[0:]) result.Writebuf[0:n]) if err != nil { if err == io.EOF { break } return nil, err } } return result.Bytes), nil }
Listennet, laddr string) Listener, error)
返回一个实现Listener接口的对象.net参数可以为”tcp”, “tcp4”, “tcp6”, “unix” 或者 “unixpacket”.
func Listennet, laddr string) Listener, error) { la, err := resolveAddr"listen", net, laddr, noDeadline) if err != nil { return nil, err } switch la := la.type) { case *TCPAddr: return ListenTCPnet, la) //监听TCP case *UnixAddr: return ListenUnixnet, la) //监听Unix } return nil, UnknownNetworkErrornet) }
看个服务端的例子
package main import "fmt" "net" "os" ) func main) { service := ":1200" listener, err := net.Listen"tcp", service) checkErrorerr) for { conn, err := listener.Accept) if err != nil { continue } go handleClientconn) } } func handleClientconn net.Conn) { defer conn.Close) var buf [512]byte for { n, err := conn.Readbuf[0:]) if err != nil { return } _, err2 := conn.Writebuf[0:n]) if err2 != nil { return } } } func checkErrorerr error) { if err != nil { fmt.Fprintfos.Stderr, "Fatal error: %s", err.Error)) os.Exit1) } }
ListenPacketnet, laddr string) PacketConn, error)
如果你想写一个UDP服务器, 有一个PacketConn的接口,和实现了该接口的方法ListenPacket.这里net参数为:udp”, “udp4”, “udp6”, “ip”, “ip4”, “ip6″或者”unixgram”
func ListenPacketnet, laddr string) PacketConn, error) { la, err := resolveAddr"listen", net, laddr, noDeadline) if err != nil { return nil, err } switch la := la.type) { case *UDPAddr: return ListenUDPnet, la) case *IPAddr: return ListenIPnet, la) case *UnixAddr: return ListenUnixgramnet, la) } return nil, UnknownNetworkErrornet) }
Dialer
type Dialer struct { Timeout time.Duration Deadline time.Time LocalAddr Addr }
DialTimeoutnetwork, address string, timeout time.Duration) Conn, error)
设置deadline,为time.Now).Addd.Timeout)
关于如何在网络上发送数据
很显然net包.提供了基本上的建立客户端与服务端的函数
这些函数会建立一个conn或者监听器,同时每个分别都拥有netFD类型参数
netFD类型抽象了各个平台,对网络的操作
netFD通过各个操作系统特有的socket接口在网络上进行发送数据包.所以是跨平台的