一直以来有许多读者朋友对TCP的传输连接建立和释放过程不是很理解,而这又是几乎网络认证中必考的知识点,包括软考、CCNA\CCNP、H3CNA\H3CNE等,为此再把笔者年度巨作,广受好评的——《深入理解计算机网络》书中的相关内容摘出来与大家分享。本书详细内容及读者评价可从这里了解:http://item.jd.com/11165825.htmlhttp://product.dangdang.com/23166396.html(目前7折促销中)

   另外,笔者最新的网络设备四大金刚图书在京东网、当当网、卓越网、互动出版网等全面热销中,详情点击:http://item.jd.com/11299332.html(京东网上购买此套装,7折促销中,还折后再减30元7折活动可能随时结束哦,欲购快快行动),http://book.dangdang.com/20130730_aife购买此套装直减30元

10.3.6 TCP传输连接建立

TCP是一个面向连接的传输层协议,所以无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条传输连接。本节将详细讨论一个TCP传输连接是如何建立的。

1. 单方主动连接的TCP连接建立过程

在TCP/IP协议体系结构中的TCP协议也是使用三次握手(three-way handshake)机制来建立传输连接的,这与在本章前面介绍的OSI/RM传输层为了避免重复连接而采取的三次握手机制是一样的。具体流程如图10-38所示,其实整体过程在上节的图10-37中有全面的体现,这里仅单独把TCP传输连接建立过程列出来。具体步骤如下:

(1)首先是服务器初始化的过程,从CLOSED(关闭)状态开始通过顺序调用SOCKET、BIND、LISTEN和ACCEPT原语创建Socket套接字,进入LISTEN(监听)状态,等待客户端的TCP传输连接请求。

(2)客户端最开始也是从CLOSED状态开始调用SOCKET原语创建新的Socket套接字,然后在需要再调用CONNECT原语,向服务器发送一个将SYN字段置1(表示此为同步数据段)的数据段(假设初始序号为i),主动打开端口,进入到SYN SENT(已发送连接请求,等待对方确认)状态。

图10-38  TCP传输连接建立的三次握手过程

(3)服务器在收到来自客户端的SYN数据段后,发回一个SYN字段置1(表示此为同步数据段),ACK字段置1(表示此为确认数据段),ack(确认号)=i+1的应答数据段(假设初始序号为j),被动打开端口,进入到SYN RCVD(已收到一个连接请求,但未进行确认)状态。这里要注意的是确认号是i+1,而不是i,表示服务器希望接收的下一下数据段序号为i+1。

(4)客户端在收到来自服务器的SYN+ACK数据段后,向服务器发送一个ACK=1(表示此为确认数据段),序号为i+1,ack=j+1的确认数据段,同时进入ESTABLISHED(连接建立)状态,建立单向连接。要注意的是,此时序号为i+1,确认号为j+1,表示客户端希望收到服务器的下一个数据段的序号j+1。

(5)服务器在收到客户端的ACK数据段后,进入ESTABLISHED状态,完成双向连接的建立。

连接可以由任一方或双方发起,一旦连接建立,数据就可以双向对等地流动,而没有所谓的主从关系。三次握手是连接两端正确同步的充要条件,因为TCP建立在不可靠的分组传输服务之上,报文可能丢失、延迟、重复和乱序,因此协议必须使用超时和重传机制。如果重传的连接请求和原先的连接请求在连接正在建立时到达,或者当一个连接已经建立、使用和结束之后,某个延迟的连接请求才到达,就会出现问题。采用三次握手协议就可以解决这些问题。如客户端发送的ACK数据段就是为了避免因网络延迟而导致的重复连接,因为这时客户端就可通过检查ACK数据段中的确认号就可得知该连接请求是否已失效。

【经验之谈】对比图10-38和本章前面的10.2.2节中的图10-20以看出,总体上TCP传输连接的建立与OSI/RM中TP传输协议的传输连接建立过程既存在相似之处(如三次握手机制),又存在较大区别的。主要表现在:①在OSI/RM中,只有DT TPDU和ED TPDU才有序列号,所以在返回的确认类TPDU中是没有TPDU序号的,所以在图10-20中并没有标注确认TPDU的序列号,而TCP传输连接中,每个数据段(无论是否携带数据)都有序列号,都需要标其对应的序列号;②因为在OSI/RM的传输协议中不同服务原语可以使用不同的特定类型TPDU,所以在OSI/RM的TPDU中不存在像TCP数据段中的ACK、SYN等之类的控制位,因为在TCP协议中所有数据段格式是一样的,不同的只是不同类型的TCP数据段的这些字段的取值不同;③TCP传输连接中使用“确认号”字段与OSI/RM TPDU中的“YR-TU-NR”(你的TPDU序列号)字段的功能是完全一样的,都是显示对端希望接收的下一个数据段序列号,暗示该号码前面的所有数据段均已正确接收。

2.    双方同时主动连接的TCP连接建立过程

正常情况下,传输连接都是由一方主动发起的,但也有可能双方同时主动发起连接,此时就会发生连接碰撞,最终只有一个连接能够建立起来。因为所有连接都是由它们的端点进行标识的。如果第一个连接请求建立起一个由套接字(x,y)标识的连接,而第二个连接也建立了这样一个连接,那么在TCP实体内部只有一个套接字表项。

当出现同时发出连接请求时,则两端几乎在同时发送一个SYN字段置1的数据段,并进入SYN_SENT状态。当每一端收到SYN数据段时,状态变为SYN_RCVD,同时它们都再发送SYN字段置1,ACK字段置1的数据段,对收到的SYN数据段进行确认。当双方都收到对方的SYN+ACK数据段后,便都进入ESTABLISHED状态。图10-39显示了这种同时发起连接的连接过程,但最终建立的是一个TCP连接,而不是两个,这点要特别注意。


图 10-39 同时发起连接的TCP连接建立流程

从图中可以看出,一个双方同时打开的传输连接需要交换4数据段,比正常的传输连接建立所进行的三次握手多交换一个数据段。此外要注意的是,此时我们没有将任何一端称为客户或服务器,因为每一端既是客户又是服务器。
10.3.7 TCP传输连接的释放

TCP 连接建立起来后,就可以在两个方向传送数据流。当 TCP的网络应用进程再没有数据需要发送时,就可以发出关闭连接命令,释放连接。TCP协议是通过发送FIN字段置1的数据段来作为关闭传输连接的命令,关闭本端数据流的,但是本端仍然还可以继续接收来自对端的数据,直到对端也使用了同样的方法关闭那个方向的数据流,这时整个双方传输连接就彻底关闭了。

1. 单方主动关闭的TCP连接释放过程

相对TCP传输连接建立的三次握手过程来说,TCP传输连接的释放过程要稍微复杂一些,需要经过四次握手过程。这是因为TCP的半关闭(half-close)特性造成的,即因这一个TCP连接是全双工(即数据在两个方向上能同时传递),每个方向必须单独地进行关闭。TCP传输连接关闭的原则是:当一方完成它的数据发送任务后就可以发送一个FIN字段置1的数据段来终止这个方向的数据发送;当另一端收到这个FIN数据段后,必须通知它的应用层“对端已经终止了那个方向的数据传送”。而FIN数据段的发送是由应用层调用CLOSE服务原语的结果。TCP连接释放的四次握手过程如图10-40所示,具体描述如下:

(1)一开始,通信双方都处于ESTABLISHED(连接建立)状态。如果客户端认为数据全部发送完了,想结束本次传输连接,则由应用层的对应应用进程调用CLOSE服务原语,然后向服务器发出一个FIN字段置1的数据段(假设此数据段的序号为m),客户端进入FIN WAIT 1状态,等待服务器的确认。

(2)服务器在收到客户端发来的FIN数据段后,确认客户端没有新的数据要发送了,向客户端发送一个ACK字段置1,确认号为m+1(假设此数据段序号为w,服务器与客户端的数据段序号可以不一样),表示前面的数据已全部收到了,然后进入到CLOSE WAIT(关闭等待)状态。与此同时服务器的TCP实体通知对应的应用层进程,释放从客户机到服务器方向的传输连接,进入半关闭状态。但此时服务器仍可以向客户端发送数据段;客户端也可接收来自服务器的数据。而且这可能要持续一段时间,直到服务器的数据也全部发送完。

图10-40 TCP传输连接释放的四次握手过程

(3)当客户端收到服务器的ACK数据段后便进入到了FIN WAIT 2状态,进一步等待服务器发出连接释放的数据段。

(4)当服务器发送完全部的数据后,其对应的应用进程也会通知TCP实体释放此方向的TCP传输连接,向客户机发送FIN字段置1,ACK字段置1,ack=m+1(假设此时的数据段序号已变为w)的确认数据段。这时服务器进入LAST ACK(最后确认)状态,等待客户端的确认。

(5)客户端在收到服务器的FIN+ACK数据段后,向服务器发送一个ACK字段置1,ack=w+1,序列号为m+1的数据段,进入到TIME WAIT状态。但此时TCP连接还没有释放,必须等待2MSL时间(RFC 793建议设MSL为2分钟)后,客户端才进入到CLOSED状态,彻底释放了TCP连接。

(6)服务器在收到客户端发来的ACK数据段后,也进入CLOSED状态,彻底释放连接。完成整个TCP传输连接释放过程。

2. 双方主动关闭的TCP连接释放流程

与可以双方同时建立TCP传输连接一样,TCP传输连接关闭也可以由双方同时主动进行(正常情况下都是由一方发送第一个FIN数据段进行主动连接关闭,另一方被动接受连接关闭),如图10-41所示。具体描述如下:


图10-41 同时主动关闭TCP连接的流程

当两端对应的网络应用层进程同时调用CLOSE原语,发送FIN数据段执行关闭命令时,两端均从ESTABLISHED状态转变为FIN WAIT 1状态。任意一方收到对端发来的FIN数据段后,其状态均由FIN WAIT 1转变到CLOSING状态,并发送最后的ACK数据段。当收到最后的ACK数据段后,状态转变化TIME_WAIT,在等待2MSL后进入到CLOSED状态,最终释放整个TCP传输连接。

TCP传输连接建立与释放详解的更多相关文章

  1. TCP报文段首部格式详解

    TCP首部格式   格式字段详解   源端口.目标端口: 计算机上的进程要和其他进程通信是要通过计算机端口的,而一个计算机端口某个时刻只能被一个进程占用,所以通过指定源端口和目标端口,就可以知道是哪两 ...

  2. ip头、tcp头、udp头详解及定义,结合Wireshark抓包看实际情况

    公司的同事们在分析网页加载慢的问题,忽然使用到了Wireshark工具,我就像发现新大陆一样好奇,赶紧看了看,顺便复习了一下相关协议.上学时学的忘的差不多了,汗颜啊! 报文封装整体结构 mac帧头定义 ...

  3. [转帖]技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解

    技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解    http://www.52im.net/thread-1309-1-1.html   本文来自腾讯资深研发工程师罗成的技术分享, ...

  4. TCP协议粘包问题详解

    TCP协议粘包问题详解 前言 在本章节中,我们将探讨TCP协议基于流式传输的最大一个问题,即粘包问题.本章主要介绍TCP粘包的原理与其三种解决粘包的方案.并且还会介绍为什么UDP协议不会产生粘包. 基 ...

  5. TCP通讯处理粘包详解

    TCP通讯处理粘包详解 一般所谓的TCP粘包是在一次接收数据不能完全地体现一个完整的消息数据.TCP通讯为何存在粘包呢?主要原因是TCP是以流的方式来处理数据,再加上网络上MTU的往往小于在应用处理的 ...

  6. IP头、TCP头、UDP头详解以及定义

    一.MAC帧头定义 /*数据帧定义,头14个字节,尾4个字节*/typedef struct _MAC_FRAME_HEADER{ char m_cDstMacAddress[6];    //目的m ...

  7. 网络基础知识-TCP/IP协议各层详解

    TCP/IP简介 虽然大家现在对互联网很熟悉,但是计算机网络的出现比互联网要早很多. 计算机为了联网,就必须规定通信协议,早期的计算机网络,都是由各厂商自己规定一套协议,IBM.Apple和Micro ...

  8. TCP/IP协议簇分层详解---转

    http://blog.csdn.net/hankscpp/article/details/8611229 一. TCP/IP 和 ISO/OSI ISO/OSI模型,即开放式通信系统互联参考模型(O ...

  9. 转-tcp建立和释放详解

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

随机推荐

  1. HDU 5584 LCM Walk(数学题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5584 题意:(x, y)经过一次操作可以变成(x+z, y)或(x, y+z)现在给你个点(ex, e ...

  2. C++学习之文件的输入输出

    C++学习之文件的输入输出        一.文件的打开与关闭        1.输出数据到文件        文件的操作需要包含fstream头文件,文件的操作对象为ifstream,ofstrea ...

  3. JQ插件开发方法

    由于项目原因,不得不写个JQ侧滑插件来满足需求.. 先引用两篇博文,待测试了 再写怎么做.. http://blog.csdn.net/business122/article/details/8278 ...

  4. python+sublime text2中文乱码[Decode error - output not utf-8]

    转自: http://blog.sina.com.cn/s/blog_765abd7b0101dtbw.html 学习,记录一下.中文编码真的挺麻烦.抽空把自己的sb3的配置写一些. 该问题让我纠结了 ...

  5. python parse命令行参数

    #!/usr/bin/env python import sys def main(argv): for arg in argv: print arg if __name__ == '__main__ ...

  6. NET Core MVC 在linux上的创建及发布

    NET Core MVC 在linux上的创建及发布 前言 ASP.NET core转眼都发布半月多了,社区最近也是非常活跃,虽然最近从事python工作,但也一直对.NET念念不忘,看过了园区大神们 ...

  7. DOCTYPE声明的几种类型

    DOCTYPE声明的几种类型 DOCTYPE 声明决定着浏览器怎么去解析和渲染当前页面,所以对于页面来说是很重要的. HTML5时代,统一用 <!DOCTYPE html> 这样简单的方式 ...

  8. Struts 和Spring的核心控制器

    Struts 核心控制器是FilterDispatch Spring核心控制器是DispatchServlet

  9. delphi调用外部程序打开文件

    delphi调用外部程序打开文件 ShellExecute的各种用法 一.利用系统默认的邮件收发器发送电子邮件 Uses ..., ShellAPI; Var lpHwnd: HWND; lpOper ...

  10. SQL SERVER表不能修改表结构的处理方法

    SQL SERVER表提示不能修改表结构,这究竟是什么原因呢?下面就为您介绍处理该问题的方法,如果您在SQL SERVER表修改方面遇到过问题,不妨一看. 新装的SQL SERVER 2008,打开原 ...