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的交互。
五、使用及实操
    了解了两种方式后,我们来进行两种链接的实际例子练习
  1.     基于流的协议
    基于流的协议使用的是上图中的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、待阅读





全部评论

相关推荐

飞花断音:这个头像有点搞笑
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务