tcp的3次握手、4次挥手

客户端与服务器之间通信:

  • 如果用的是udp,客户端给服务器发送的数据到底收没收到,客户端是不知道的,udp是直接发送
  • 如果用的是tcp,其一大特点是,客户端的操作系统底层会和服务器的操作系统底层建立连接,一方发送的数据,另一方会回复已收到,tcp在发送数据之前,会先建立链接,即tcp的三次握手
    • 例如,客户端要给服务器发送一个数据“hello”
    • 客户端先发送一个数据包告诉服务器:我要链接你(今晚你在吗?)
    • 服务器收到这个数据后会立马回复客户端:好的,啥时候链接(在的,你要来吗?)
    • 客户端收到回复之后立马也给服务器回复:一会就链接(一会就来)
    • 这时三次握手完成,即准备资源的过程完成

3次握手:

tcp的3次握手、4次挥手_第1张图片

  • 1、客户端(Client)调用connect发送链接请求报文syn给服务器,并携带序列号11,告诉服务器,我要给你发送数据了,你准备好了吗

  • 2、服务器(server)收到请求报文之后,给客户端回复确认报文ack,并将序列号加1(11+1=12),告诉客户端我准备好了

    • 上面1、2这一来一回,对于客户端而言,知道服务器已经准备好了资源,那么服务器怎么知道客户端也准备好了资源呢,按照1、2两步的思想
  • 3、服务器给客户端发送了确认报文之后,再发送请求报文syn给客户端,并携带序列号22,告诉客户端,你准备好发送数据了吗

  • 4、客户端收到请求报文之后,给服务器回复确认报文ack,并将序列号加1(22+1=23),告诉服务器,我也准备好了

    • 下面3、4这一来一回,对于服务器而言,知道客户端已经准备好了资源
  • 这样来来回回4次,才能让收发双方真正准备好资源

  • 准备好资源之后,接下来客户端向服务器发送一个hello world,服务器操作系统底层才会悄悄的告诉你收到了,这就保证了收发数据不会丢失

  • 问题来了:

    • 按照上面讲述的过程,应该是4次握手呀,为啥是3次握手呢?
      • 当用户打开一个网站的时候,目的只有一个,想尽快的打开网站,而不会关心客户端与服务器是3次握手还是4次握手,而只想让网站快点,也就是提高用户体验感觉,一个字,比如你打开百度1s就打开了,结果打开谷歌2分钟都没打开,你是不是想问候一下它全家呢
      • 那么能减少的次数,我们是不是可以减少减少啊,为了让用户爽,我们怎么做呢
        • 我们把上述步骤2步骤3合并,服务器收到请求报文之后,给客户端回复确认报文ack的同时,向客户端发送请求报文syn
        • 这样我们便实现了客户端与服务器之间的3次握手,提高了数据传输效率,节省了数据传输时间,让用户感觉到爽
      • 保证了收发栓发在发送数据之前准备好资源,所以说是3次握手,具体过程如下:

tcp的3次握手、4次挥手_第2张图片

随着我们收发数据结束,不想通信了,想要关闭,怎么办呢,只要双方释放资源即可,便有了接下来我们要讲的4次挥手

4次挥手

  • 一般是客户端先关闭,客户端先跟服务器说我不跟你玩了,然后服务器收到之后说好的,服务器紧接着又说我也不跟你玩了,客户端收到之后说好的
  • 来来回回四次,便关闭了整个通信,因为套接字是全双工的,有两个通道,一个是收数据的,一个是发数据的,关的时候,必须两个全关了,才真正的关闭,具体如图所示。

tcp的3次握手、4次挥手_第3张图片

  • 1、当客户端不想给服务器发送数据的时候,客户端一定会调用xxx.close(),这时客户端的操作系统底层会向服务器发送一个终止请求fin,并携带一个序列号33,告诉服务器,我不会在向你发送数据了
  • 2、服务器的操作系统底层会向客户端回复一个确认报文ack,并将序列号加1(33+1=34),告诉客户端我收到了,并通知应用程序,客户端不会向你发送数据了,这时服务器的服务套接字new_socket.recv()会解堵塞
  • 3、服务器解堵塞之后,应用程序继续向下执行,当遇到new_socket.close()之时,服务器便调用new_socket.close()关闭服务套接字,向客户端发送一个终止请求fin,并携带序列号44,告诉客户端我也不给你发送数据了,并在这里等待一段时间(即超时时间),直到收到客户端的确认消息之后,便彻底不在向客户端发送数据
  • 4、客户端收到终止请求之后,会向服务器发送确认报文ack,并将序列号加1,告诉服务器,我也收到了,并在这里等待一段时间(一般是2个报文生命周期),此时收发双方真正关闭通信,释放资源,

关键1:为什么不是3次挥手,而是4次挥手

  • 因为服务器收到客户端关闭发送的消息,并给客户端回复我收到了之后,并不一定会立马就关闭服务套接字,有可能会延时,所以是4次,不是3次

关键2:

  • 无论是服务器还是客户端,谁先调用了close,即谁先决定不再向对方发送数据了,谁便在最后等待2个报文生命周期的时间,也就是说,谁先调用close,谁的资源就会在电脑中保留一段时间,在这个期间之内,这份资源不能重复使用
  • 假如是服务器先调用close,服务器的资源就会在电脑中保留一段时间,在这个期间之内,这份资源不能重复使用,言外之意就是你的端口此时被占用,不能重复使用

最简单的理解

3次握手

  • 客户端:我要对你讲话,你能听到吗
  • 服务端:我能听到,而且我也要对你讲话,你能听到吗
  • 客户端:我也能听到
    …….
    互相开始通话
    ………

4次挥手

  • 客户端:我说完了,我要闭嘴了
  • 服务端:我收到请求,我要闭耳朵了(客户端收到这个确认,于是安心地闭嘴了。)
    …….
    服务端还没倾诉完自己的故事,于是继续唠唠叨叨向客户端说了半天,直到说完为止
    …….
  • 服务端:我说完了,我也要闭嘴了,在这里继续等待客户端回应自己
  • 客户端:我收到请求,我要闭耳朵了(事实上,客户端为了保证这个确认包成功送达,等待了两个最大报文生命周期后,才闭上耳朵。)
  • (服务端收到这个确认,于是安心地闭嘴了。)

你可能感兴趣的:(tcp的3次握手、4次挥手)