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、待阅读

