服务器初始化
(1)调用socket,建立文件描述符
(2)调用bind,将文件描述符与ip/port链接起来。若端口号已被占用,则bind失败
(3)调用listen,声明该文件描述符是服务器的一个文件描述符,为以后的accept作准备
(4)调用accept,并处于阻塞状态,等待客户端链接
创建链接
(1)调用socket,建立文件描述符
(2)调用connect,向服务器发起链接请求。
(3)connect会发送一个请求SYN段并阻塞等待服务器应答(第一次)
(4)服务器收到SYN,会给客户端发送一个确认应答的同时发送一个请求(SYN+ACK),表示赞成创建链接(第二次)
(5)客户端收到客户端发的SYN+ACK段,代表客户端链接已创建成功,进入ESTABLISHED状态,从connect()。客户端再向服务器发送一个ACK段,服务器收到后则服务器端链接也创建成功,服务器也进入ESTABLISHED状态。
数据传输
(1)链接创建成功后,在同一链接、同一时刻,通讯双方可同时写数据(全双工)
(2)服务器端从accept()返回后调用read()开始读数据,若没有数据则阻塞等待
(3)客户端调用write()向服务器发送数据请求,客户端收到以后调用read()处理请求,此过程服务器调用read()阻塞等待
(4)服务器调用write()将处理好的请求发送给客户端,再次调用read()等待下一个请求
(5)客户端收到后从read()返回,发送下一条请求,如此循环下去web
断开链接
(1)没有数据处理了,则客户端调用close()关闭链接,给服务器端发送一个断开链接请求FIN段(第一次)
(2)服务器收到客户端的FIN段,给客户端发送一个确认应答ACK段代表赞成断开链接,客户端收到ACK段并调用read()返回0,代表客户端链接已断开(第二次)
(3)read()返回0以后,服务器知道客户端已断开链接,它也调用close()关闭链接,给客户端发送一个断开链接请求FIN段(第三次)
(4)客户端接收到服务器端发送的FIN段,给服务器一个确认应答ACK段,代表赞成断开链接。客户端进入TIME_WAIT状态,服务器收到客户端的ACK后则服务器断开链接。
服务器
总结:
1.为何是三次握手而不是两次或四次握手?
(1)若是是两次握手,则客户端发送链接请求SYN,服务器端接收链接请求并给客户端发送一个ACK进入ESTABLISHED状态,服务器端认为链接创建成功。有可能服务器端发送的ACK在传输过程当中丢了,客户端没有收到ACK从而认为链接没有创建成功。客户端认为链接没有创建成功则会不停的发送链接请求,而服务器认为链接成功则须要文虎相应的资源来管理链接,但这个链接无心义,服务器在维护的时候会浪费服务器资源。形成空间与时间上的浪费,从而形成内存泄漏的问题。四次握手问题同二次握手。
(2)三次握手的最后一次传送数据有可能也会形成丢包问题,可是此时客户端认为链接创建成功而服务器认为链接创建没成功,对服务器没有太大的消耗。客户端给服务器端发送数据,服务器端不进行接收。
三次握手已经知足需求就不须要更屡次的握手。
(3)创建链接是双方的事情,双方都须要创建链接再互相确认,有点像四次握手。可是由于由于TCP能捎带应答,因此服务器向客户端的请求创建链接的SYN以及对客户端的ACK能够一块儿发送,从而致使了三次握手。
2.为何是四次挥手?
* 释放链接是两方的事情,双方发送断开链接请求后还须要确认,并且服务器对客户端的ACK以及FIN不能合并,因此是四次挥手
* 服务器端对客户端的FIN及ACK不能合并是由于客户端断开链接代表客户端没有数据发送给服务器了,不带表服务器没有数据发给客户端,则服务器向客户端发送ACK以后到服务器发送FIN之间有时间间隔,因此两步骤不能合并
3.为何有TIME_WAIT状态?
如服务器端将最后一个断开链接请求发送以后,客户端收到FIN后给服务器端发送一个确认应答ACK,但在传输过程当中可能会丢包,这个ACK没有被服务器收到。当服务器在必定时间内没有收到ACK时会从新发送请求,因此客户端须要一个TIME_WAIT时间等待,解决丢包重传问题。一个TIME_WAIT的时间是2MSL。
哪一方先断开链接就先进入TIME_WAIT等待时间。socket