C++--问题25--socket通信流程
1.什么是Socket?
网络中的进程是通过socket来通信的。socket起源于 Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,socket是“open—write/read—close”模式的一种实现,那么socket就提供了这些操作对应的函数接口。
2.socket通信流程
以使用TCP协议通讯的socket为例,其交互流程大概是:
(1)socket():函数就是生成一个用于通信的套接字文件描述符,这个套接字描述符可以作为稍后bind()函数的绑定对象。
服务器根据地址类型(ipv4,ipv6)、socket类型、协议创建socket。
(2)bind():服务程序通过分析配置文件,从中解析出想要监听的地址和端口,再加上可以通过socket()函数生成的套接字sockfd,就可以使用bind()函数将这个套接字绑定到要监听的地址和端口组合"addr:port"上。绑定了端口的套接字可以作为listen()函数的监听对象。
服务器为socket绑定ip地址和端口号。
(3)listen():int listen(int sockfd, int backlog); 这是内核源码中listen函数的定义,sockfd 就是bind函数关联后的套接字文件描述符。
backlog:Linux Kernel2.2以前,backlog 用于设置上图中未完成和已完成队列的最大总长度(实际上是只有一个队列,但分为两种状态),实际目前这种是BSD衍生的一种套接字类型,它采用了一个队列,在这单个队列中存放3次握手过程中的所有连接,但是队列中的每个连接分为两种状态:syn-recv和established。Linux Kernel2.2开始,这个参数只表示已完成队列(accept queue)的最大长度。(面试会被问到第二个参数的意义)
服务器socket监听端口号请求,随时准备接收客户端发来的连接,这时候服务器的socket并没有被打开。
(4)socket():客户端创建socket,生成文件描述符。
(5)connect():客户端打开socket,根据服务器ip地址和端口号试图连接服务器socket。
(6)accept():服务器socket接收到客户端socket请求,被动打开,开始接收客户端请求,直到客户端返回连接信息。这时候socket进入阻塞状态,所谓阻塞即accept()方法一直到客户端返回连接信息后才返回,开始接收下一个客户端连接请求。
客户端连接成功,向服务器发送连接状态信息。
服务器accept方法返回,连接成功。
(7)send():客户端向socket写入信息。
(8)recv():服务器读取信息。
(9)close():客户端关闭。
(10)close():服务器端关闭。