准备知识: 

单工:信息只能单向传递。发送-->接收,单向,不能返回响应。

双工:指的是信息可双向发送。

全双工:信息可同时双向传递。

半双工:不能同时,单行道,一边传输完了,另一边才能发起传输。

由于IP协议是不可靠的,为了在不可靠信道上传输可靠数据,就要进行三次握手,准确的说是发送三次预备信息,这样就完成了信息传递的双工准备。(HTTP协议是需要双向传递的)。

双方都需要确认自己的发信和收信功能正常,收信功能通过接收对方信息得到确认,发信功能需要发出信息—>对方回复信息得到确认。

第一次发信息: CLIENT --> SERVER

第二次发信息:  SERVER --> CLIENT     客户端接收到了,确信自己可以收,并且收到的信息里有上一步发过去信息里的内容,说明也是可以发送的。

第三次发信息: CLIENT --> SERVER     同理,服务端也确信了可以收和发的能力。

如果没有第三次发信息,只是保证了一个单向的连接畅通。客户端可以大胆地单向给服务端发信息。服务端由于没收到过“回音”,不能确定对方能不能收到,tcp协议是保证了传输可靠性的,不允许这种不确定性存在,就不允许服务器给客户端发送响应了。

当然UDP协议就不保证输出的可靠性了,就算没有收到过“回音”也敢发出信息。

-------------------------------连接断开的时候为什么要四次呢-----------------

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。

因为可以同时双向传输,A B 两个终端上有两个通道四个端口。分别是A端的读端口,A端的写端口和B端的读端,B端的写端口。

TCP采用四次挥手关闭连接如图2所示。

以客户机发起关闭连接为例:
1.Client发送FIN给Server,Server收到Fin信息后知道已经没有要再接收的东西了,就关闭自己的读端口,然后发送ACK给CLient   --Server 读端关闭 
2.Client收到ACK后,知道对面已经关闭读通道了,现在自己可以把写端口关闭了                                                                    --Client  写端关闭
3.Server发送FIN给Client表示自己没有要发送的了,Client收到FIN后,关闭自己的读端口,然后发送ACK给Server                  --Client  读端关闭
4.Server接受到ACK后,关闭自己的写端口,并且Server的Conection状态变为Closed,彻底关闭可以重用了。                        --Server 写端关闭 
5.Client在最后发给Server的ACK报文后等待两个MSL时间,然后Client端的onection状态变为Closed。

* 可以看出,读端口的关闭,是收到对方发来的FIN信号即可。而写端口的关闭是,发送一个FIN给对方,收到对方的ACK回复才可以关闭。这是确保数据包都发送过去的重发机制要求的。

第2步和第3步很多时候都可以合并,就是收到对方的FIN的时候,自己没有要发过去的东西,就把ACK和FIN一起返回去了。

* 主动发起关闭连接的一方发出最后的ACK报文后达到TIME_WAIT状态,而且这个状态要保持Maximum Segment Lifetime的两倍时间。这是因为两点:

保证TCP协议的全双工连接能够可靠关闭
2 保证这次连接的重复数据段从网络中消失

先说第一点,如果Client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN,此时由于Client已经CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST而不是ACK,Server就会以为是连接错误把问题报告给高层。这种情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。所以,Client不是直接进入CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候再发一个ACK给对方。保证对方收到,最后正确的关闭连接。(MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间,为操作系统决定大小,windows默认MSL值为2分钟。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。)

再说第二点,如果Client直接CLOSED,然后又再向Server发起一个新连接,我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达Server,由于新连接和老连接的端口号是一样的,又因为TCP协议判断不同连接的依据是socket pair,于是,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以保证本次连接的所有数据都从网络中消失。

------------------TCP的粗暴关闭连接方式--------------------

除了如上可靠的关闭方式之外,TCP还提供了另外一种不可靠的关闭方式RST(Reset)
(CLOSED)  A    ---RST-->  B (CLOSED)
  A端发送RST状态之后,TCP进入CLOSED状态,B端接收到RST后,也即可进入CLOSED状态。
在上面第一关闭方式上(可靠的),非常遗憾,A端在最后发送一个ACK请求后,并不能马上将该Socket回收,因为A并不能确定B一定能够接收到这个ACK报文,因此A端必须对这个Socket维持TIME_WAIT状态2MSL。

如果A端是Client,这并不会成为问题,但如果A端是Server,那就很危险了,如果连接的Socket非常多,而又维持如此多的TIME_WAIT状态的话,那么有可能会将Socket耗尽(报Too Many Open File)。

服务端为了解决这个问题,可选择的方式有三种:
    Ø  保证由客户端主动发起关闭(即做为B端)
    Ø  关闭的时候使用RST的方式
    Ø  对处于TIME_WAIT状态的TCP允许重用
一般我们当然最好是选择第一种方式,实在没有办法的时候,我们可以使用SOCKET参数【SO_LINGER】开启第二种方式,使用SOCKET参数【SO_REUSEADDR】开启第三种方式

tcp为什要三次握手的更多相关文章

  1. TCP/IP具体解释--三次握手和四次握手 Dos攻击

    TCP连接的状态图 TCP建立连接的三次握手过程,以及关闭连接的四次握手过程 贴一个telnet建立连接,断开连接的使用wireshark捕获的packet截图. 1.建立连接协议(三次握手) (1) ...

  2. TCP协议中的三次握手和四次挥手(图解)【转】

    建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的. [更新于2017.01.04 ]该部分内容配图有误,请大家见谅,正确的配图如下,错误配图也不删 ...

  3. TCP常见的定时器三次握手与四次挥手

    1.TCP常见的定时器 在TCP协议中有的时候需要定期或者按照某个算法对某个事件进行触发,那么这个时候,TCP协议是使用定时器进行实现的.在TCP中,会有七种定时器: 建立连接定时器(connecti ...

  4. TCP的基本概念三次握手,四次挥手

    TCP的特性 TCP提供一种面向连接的.可靠的字节流服务 在一个TCP连接中,仅有两方进行彼此通信.广播和多播不能用于TCP TCP使用校验和,确认和重传机制来保证可靠传输 TCP使用累积确认 TCP ...

  5. TCP的连接(三次握手)和释放(四次挥手)

    1 http都设置哪些header? http协议规定:一个完整的客户端发送给服务端的HTTP请求包括: (1)请求行:包括了请求方法.请求资源路径.HTTP协议版本,eg:GET/Server/im ...

  6. python网络编程-TCP协议中的三次握手和四次挥手(图解)

    建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的. 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资 ...

  7. TCP协议中的三次握手和四次挥手(图解)

    建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的. 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资 ...

  8. 通俗易懂地讲解TCP建立连接的三次握手和释放连接的四次挥手

    TCP建立连接时,为什么要进行三次挥手? 每一次TCP连接都需要三个阶段:连接建立.数据传送和连接释放.三次握手就发生在连接建立阶段. 在谢希仁著<计算机网络>第四版中讲三次握手的目的是为 ...

  9. [转]TCP协议中的三次握手和四次挥手(图解)

    本文转自:http://blog.csdn.net/whuslei/article/details/6667471 建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来 ...

  10. 【转】 TCP协议中的三次握手和四次挥手(图解)

    建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的. 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资 ...

随机推荐

  1. fir.im Weekly - 新开发时代,每个人都在创造

    七夕纷纷扰扰地过去了,身边的程序员们依旧安静从容地写代码.可是满屏幕的"对象",不如身边一个对象(。・`ω´・)- 闲话说完,这周像往期一样为大家收集了一些优秀的 GitHub 资 ...

  2. 分析system_call中断处理过程

    分析system_call中断处理过程 上周我们使用gcc内嵌汇编调用系统调用,这次我们具体分析下过程. 将getpid嵌入menuos 代码从github下载,步骤如下: 1. 增加一个函数,get ...

  3. Leetcode 225 Implement Stack using Queues STL

    用两个队列去实现栈,这里我使用了队列数组q[2],在所有的过程中保证一个队列是空的 push时插入到空的队列中,然后将队列中的元素移到另一个队列中 pop时从不空的队列中pop() peek时从不空的 ...

  4. HandlerMapping 详解

    HandlerMapping 详解 1. 导言 万丈高楼平地起,SpringMVC的辉煌离不开每个组件的相互协作,上一章详细阐述了SpringMVC整个体系结构及实现原理,知道HandlerMappi ...

  5. Java 中的instanceof简单讲解

    Java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例.instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例. 用法:resu ...

  6. [Aaronyang] 写给自己的WPF4.5 笔记23 [3d交互与动画 4/4]

    效果图预览: 1. 3d中的命中测试 我新建了一个空的窗口,用zam做了一个长方体,深度很小.然后导出xaml <Viewport3D x:Name="ZAM3DViewport3D& ...

  7. 【Android源代码下载】收集整理android界面UI效果源码

    在Android开发中,Android界面UI效果设计一直都是很多童鞋关注的问题,今天给大家分享下大神收集整理的多个android界面UI效果,都是源码,都是干货,贡献给各位网友! 话不多说,直接上效 ...

  8. db2 ha create dependency failed 解决

    db2diag.log 2014-10-16-23.27.55.009490-240 E31979E444 LEVEL: ErrorPID : 6651 TID : 140508206864160 P ...

  9. [转] The program can't start because api-ms-win-crt-runtime-l1-1-0.dll is missing

    https://www.smartftp.com/support/kb/the-program-cant-start-because-api-ms-win-crt-runtime-l1-1-0dll- ...

  10. 关于Unity程序在IOS和Android上显示内嵌网页的方式

    近期因为有须要在Unity程序执行在ios或android手机上显示内嵌网页.所以遍从网上搜集了一下相关的资料.整理例如以下: UnityWebCore 从搜索中先看到了这个.下载下来了以后发现这个的 ...