Linux网络编程中connect()、listen()和accept()与TCP三次握手的关系
Linux网络编程开发分为服务器端和客户端两个部分:
对于服务器端的流程——类似于接电话过程
socket()[找到一个可以通话的手机]----->bind()[插入一个固定号码]------>listen()[随时准备接听]-------> accept------->recv()------->send()------>close();
对于客户端的主要流程----类似于打电话过程
socket()----->connect()------>recv/read/send------>close()
三个接口函数介绍
1. connect()函数:是一个阻塞函数通过TCP三次握手建立连接
客户端主动连接服务器,通过TCP三次握手通知Linux内核自动完成TCP 三次握手连接 如果连接成功为0 失败返回值-1
一般的情况下客户端的connect函数,默认是阻塞行为,直到三次握手阶段成功为止。
2. 服务器端的listen() 函数:不是一个阻塞函数: 功能:将套接字和套接字对应队列的长度告诉Linux内核。
他是被动连接的一直监听来自不同客户端的请求, listen函数将socketfd 变成被动的连接监听socket 其中参数backlog作用设置内核中队列的长度 。
注:listen的函数形式int listen(int sockfd, int backlog); backlog代表listen队列的长度。
3. accept() 函数阻塞:从处于established 状态的队列中取出完成的连接,当队列中没有完成连接时候,会形成阻塞,直到取出队列中已完成连接的用户连接为止(Accept默认会阻塞进程,直到有一个客户连接建立后返回)。
对应关系
在TCP/IP详解中,这三个函数与TCP三次握手之间的对应关系是这样的
- 服务器调用listen进行监听
- 客户端调用connect来发送syn报文
- 服务器协议栈负责三次握手的交互过程。连接建立后,往listen队列中添加一个成功的连接,直到队列的最大长度。
- 服务器调用accept从listen队列中取出一条成功的tcp连接,listen队列中的连接个数就少一个
总结一下就是:
- TCP的三次握手是有客户端调用connect()函数以及服务器端的协议栈共同完成的。
- 服务器端的listen函数负责监听客户端的连接请求,并维护一个listen队列,当有客户端连接成功时,就把它放在listen队列里。
- accept()函数负责查看listen队列里面有没有成功连接,如果有则从队列中取出,没有则阻塞(直到获得一个成功连接返回)。它每取出一个成功连接,就会生成一个对应的accept fd,用于唯一标识该连接成功的客户端。
附加:TCP建立连接的时候connect()函数和accept()函数分别在三次握手第几次后返回()