欢迎访问生活随笔!

生活随笔

您现在的位置是:首页 > 形式科学 > 计算机科学 > IT网络

IT网络

网络数据包拨号和监听监控

发布时间:2022-11-11IT网络 小博士
到目前为止,我们已经区分了TCP和UDP API的区别,并使用示例DialTCP和DialUDP分别返回一个TCPConn和UDPConn。Conn类型是一个接口,由TCPConn和UDPConn实现。

今为止我们已经区分TCP和UDP API的不同,使用例子DialTCP和DialUDP分别返回一个TCPConn和 UDPConn。Conn类型是一个接口,TCPConn和UDPConn实现了该接口。在很大程度上,你可以通过该接口处理而不是用这两种类型。

Dial(network, 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 len(os.Args) != 2 { fmt.Fprintf(os.Stderr, 'Usage: %s host:port', os.Args[0]) os.Exit(1) } service := os.Args[1] conn, err := net.Dial('tcp', service) checkError(err) _, err = conn.Write([]byte('HEAD / HTTP/1.0 ')) checkError(err) result, err := readFully(conn) checkError(err) fmt.Println(string(result)) os.Exit(0) } func checkError(err error) { if err != nil { fmt.Fprintf(os.Stderr, 'Fatal error: %s', err.Error()) os.Exit(1) } } func readFully(conn net.Conn) ([]byte, error) { defer conn.Close() result := bytes.NewBuffer(nil) var buf [512]byte for { n, err := conn.Read(buf[0:]) result.Write(buf[0:n]) if err != nil { if err == io.EOF { break } return nil, err } } return result.Bytes(), nil }

Listen(net, laddr string) (Listener, error)

返回一个实现Listener接口的对象.net参数可以为'tcp', 'tcp4', 'tcp6', 'unix' 或者 'unixpacket'.

func Listen(net, laddr string) (Listener, error) { la, err := resolveAddr('listen', net, laddr, noDeadline) if err != nil { return nil, err } switch la := la.(type) { case *TCPAddr: return ListenTCP(net, la) //监听TCP case *UnixAddr: return ListenUnix(net, la) //监听Unix } return nil, UnknownNetworkError(net) }

看个服务端的例子

package main import ( 'fmt' 'net' 'os' ) func main() { service := ':1200' listener, err := net.Listen('tcp', service) checkError(err) for { conn, err := listener.Accept() if err != nil { continue } go handleClient(conn) } } func handleClient(conn net.Conn) { defer conn.Close() var buf [512]byte for { n, err := conn.Read(buf[0:]) if err != nil { return } _, err2 := conn.Write(buf[0:n]) if err2 != nil { return } } } func checkError(err error) { if err != nil { fmt.Fprintf(os.Stderr, 'Fatal error: %s', err.Error()) os.Exit(1) } }

ListenPacket(net, laddr string) (PacketConn, error)

如果你想写一个UDP服务器, 有一个PacketConn的接口,和实现了该接口的方法ListenPacket.这里net参数为:udp', 'udp4', 'udp6', 'ip', 'ip4', 'ip6'或者'unixgram'

func ListenPacket(net, laddr string) (PacketConn, error) { la, err := resolveAddr('listen', net, laddr, noDeadline) if err != nil { return nil, err } switch la := la.(type) { case *UDPAddr: return ListenUDP(net, la) case *IPAddr: return ListenIP(net, la) case *UnixAddr: return ListenUnixgram(net, la) } return nil, UnknownNetworkError(net) }

Dialer

type Dialer struct { Timeout time.Duration Deadline time.Time LocalAddr Addr }

DialTimeout(network, address string, timeout time.Duration) (Conn, error)

设置deadline,为time.Now().Add(d.Timeout)

关于如何在网络上发送数据

很显然net包.提供了基本上的建立客户端与服务端的函数

这些函数会建立一个conn或者监听器,同时每个分别都拥有netFD类型参数
netFD类型抽象了各个平台,对网络的操作
netFD通过各个操作系统特有的socket接口在网络上进行发送数据包.所以是跨平台的