准备知识: 

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

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

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

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

由于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. spring 配置定时任务

    spring的定时任务配置分为三个步骤:1.定义任务2.任务执行策略配置3.启动任务1.定义任务 <!--要定时执行的方法--> <bean id="testTaskJob ...

  2. python基于LeanCloud的短信验证

    python基于LeanCloud的短信验证 1. 获取LeanCloud的Id.Key 2. 安装Flask框架和Requests库 pip install flask pip install re ...

  3. H5小游戏的坑点小结

    坑点: 1) iOS 9.1 的safari中,在onTouchBegan方法中调用cc.audioEngine.playEffect播放音效是没有效果的,如果在onTouchEnded调用则是正常的 ...

  4. 多台linux服务器时间同步

    1,设置A机时间服务器: a,修改 /etc/ntp.conf,如下: # Undisciplined Local Clock. This is a fake driver intended for ...

  5. java 调用微信截图工具

  6. json字符串转成 Map/List

    package jsonToMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import n ...

  7. 使用Android Studio打Andorid apk包的流程

    启动Android studio   1.点击菜单栏Build -> Generate Signed APK...,打开如下窗口 2.这里是类似eclipse中Android的签名,假设这里没有 ...

  8. 如何通过Socket TCP发送并接收一个文件?

    一.小结 1.大包发小包收,只发一次. 2.发时把文件扩展名,文件长度也随同一起发送,方便接收端接收时另存为正确的文件类型,并判断是否已经接收完毕. 如果不一起发送,分为文件扩展名,文件长度,文件内容 ...

  9. 利用Mysql提供的字符串方法查找字符串中某字符出现的次数

    有这么一个需求,查出分类中没有子分类的一级分类,脑海中首次出现的解决思路和这样的 先使用PHP查出所有的一级分类 递归查询一级分类是否有子分类 将没有子分类的一级分类汇总 但觉的这样处理太麻烦了,然后 ...

  10. Scala 深入浅出实战经典 第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...