TCP协议的通讯流程(三次握手四次挥手)高频考点!!!

TCP协议的通讯流程

让我们画一下三次握手和四次挥手,这个过程在传输层里,在操作系统中

TCP协议的通讯流程(三次握手四次挥手)高频考点!!!
在进行三次握手之前,要先进行客户端和服务器的连接,这个过程的创建是有成本的,时间成本和空间成本

服务器初始化:

  • 调用socket,创建文件描述符
  • 调用bind,将当前文件描述符和ip/port(端口号)绑定起来;如果这个端口号以及被其它程序占用了,就会bind失败
  • 调用listen,声明当前这个文件描述符作为一个服务器的文件描述符,为后面的accept做好准备
  • 调用accept,并阻塞,等待客户端连接过来

建立连接(客户端)的过程:

  • 调用socket,创建文件描述符
  • 调用connect(),向服务器发起连接请求
  • connect会发出SYN段并阻塞等待服务器应答;(第一次)
  • 服务器收到客户端的SYN,会应答一个SYN-ACK段表示“同意进行连接”;(第二次)
  • 客户端收到SYN-ACK会从connect()返回,同时应答一个ACK段;(第三次)

这个建立连接的过程,通常称为 三次握手

数据传输的过程:

  • 建立连接后,TCP协议提供全双工的通信服务; 所谓全双工的意思是, 在同一条连接中, 同一时刻, 通信双方 可以同时写数据; 相对的概念叫做半双工, 同一条连接在同一时刻, 只能由一方来写数据;
  • 服务器从accept()返回后立刻调 用read(), 读socket就像读管道一样, 如果没有数据到达就阻塞等待;
  • 这时客户端调用write()发送请求给服务器, 服务器收到后从read()返回,对客户端的请求进行处理, 在此期 间客户端调用read()阻塞等待服务器的应答;
  • 服务器调用write()将处理结果发回给客户端, 再次调用read()阻塞等待下一条请求;
  • 客户端收到后从read()返回, 发送下一条请求,如此循环下去;

断开连接的过程:

  • 如果客户端没有更多请求了,就调用close()关闭连接,客户端向服务器发送FIN段;(第一次)
  • 此事服务器收到FIN后,会回复一个ACK,同时read会返回0;(第二次)
  • read返回之后,服务器就知道客户端关闭了连接,也调用close关闭连接,这个时候服务器会向客户端发送一个FIN;(第三次)
  • 客户端收到了FIN,在返回一个ACK给服务器;(第四次)

这个断开的过程,通常称为 四次挥手。

为什么一定要三次握手?不能是两次或者四次吗?

三次握手是在安全可靠的基础上,握手次数最少的方案。两次握手并不能保证可靠性。四次握手又浪费了效率

现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的***,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。

为什么连接的时候是三次握手,关闭的时候却是四次握手?

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。
但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。