Go标准库学习——net
一、概述
net 包为网络IO提供了一个便携式接口,包括TCP/IP,UDP,域名解析和Unix域套接字。由网络IO前景知识我们知道,网络IO需要两个机器间的通信,从一台机器的用户态到内核态,通过网卡和网络传输介质到达另一台机器的内核态再传给用户态。那么在这两台机器的操作系统(内核态)之间,net作为Go语言中的网络编程库,提供了linux中socket网络编程近似的功能。
二、不同操作系统采用方式
1、在linux上
在linux上一切皆文件。所以各端口的读写服务可以认为是读取/写入文件,一般使用文件描述符fd表示。
2、在windows上
在windows上,各端口的读写服务是一个通信链的句柄操作,通过句柄实现网络发出请求和读取数据。
3、在go上
在go上为了统一,采用Linux的fd代表一个链接节点。
三、提供接口
net包作为go网络编程库,提供了包括TCP/IP,UDP,域名解析和Unix域套接字。
1、TCP是面向连接的、可靠的流协议,可以理解为不断从文件中读取数据(STREAM)。
2、UDP是无连接的、面向报文的协议,是无序,不可靠的(DGRAM)(目前很多协议都是基于UDP开发的)。
3、UNIXDomain Socket是一种进程间通信协议,虽然是一个IPC协议,但是在实现上是基于套接字(Socket)实现的。
4、UNIXDomain Socket也可以选择采用比特流的方式,或者无序的,不可靠的通讯方式,有序数据包的方式。
四、接口及实现
下图转载自参考资料1,为net包中的接口和实现
由上图可见,总体而言net分为包链接和流链接两类。对于tcp只实现了Coon接口对应的流链接,而对于udp实现了流链接和包链接两种方式。基于 TCP、UDP、IP、Unix (Stream 方式)的链接抽象出来都是 Conn 接口。基于包传递的 UDP、IP、UnixConn (DGRAM 包方式) 都实现了 PacketConn 接口。对于面向流的监听器,比如: TCPListener、 UnixListener 都实现了 Listener 接口。
针对不同的平台,调用不同平台套接字的系统调用即可。直观上看,对于不同的链接,我们都是可以通过Conn 的接口来做网络IO的交互。
五、使用及实操
了解了两种方式后,我们来进行两种链接的实际例子练习
- 基于流的协议
基于流的协议使用的是上图中的coon接口,有tcp、unix、ip、udp和tcp监听器和unix监听器几种链接方式。基于流的协议需要先跟对端建立链接,然后再发送消息(参考tcp三次握手,先建立连接后再传送信息)。下图是Unix套接字编程的流程图
具体流程为,首先服务端绑定并监听端口,然后等待客户端建立连接。待客户端通过Dail()函数进行连接操作后,服务端使用Accept与客户端建立好连接后,开始读写消息。最后,当客户端消息发送完后,发送断开连接请求(一般情况下客户端先发起,参考tcp四次挥手),服务端收到EOF标识后,关闭连接。这是一个参考tcp的安全的流式通信协议的客户端服务器通信模型。
- 服务端编写
func main() { // 解析服务端监听地址,本例以tcp为例 addr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:8000") if err != nil { log.Panic(err) } // 创建监听器 listen, err := net.ListenTCP("tcp", addr) if err != nil { log.Panic(err) } for { // 监听客户端连接请求 conn, err := listen.AcceptTCP() if err != nil { continue } // 处理客户端请求 这个函数可以自己编写 go HandleConnectionForServer(conn) } }
- 客户端编写
func main() { // 解析服务端地址 RemoteAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:8000") if err != nil { panic(err) } // 解析本地连接地址 LocalAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1") if err != nil { panic(err) } // 连接服务端 conn, err := net.DialTCP("tcp", LocalAddr, RemoteAddr) if err != nil { panic(err) } // 连接管理 HandleConnectionForClient(conn) }
2.基于包的协议
基于包的协议支持了常见的udp、unix(dgram包方式,packetcoon方式)、ip(网络层协议,支持了icmp、igmp)几种。基于包的协议在绑定了端口后,不需要建立连接,是一种即发即收的模式(参考udp通信协议)。下图是基于包请求流程图
参考资料
1、golang net包学习和实战
2、go语言标准库学习之net——有趣的网络编程
3、待阅读