TCP/IP协议栈详解

来源:互联网 发布:js中readonly 编辑:程序博客网 时间:2024/05/22 02:07

TCP/IP协议族

1.1 简介

TCP/IP协议族由5层组成:物理层、数据链路层、网络层、运输层和应用层。前四层与OSI模型的前四层相对应,提供物理标准、网络接口、网际互联、以及运输功能。而应用层与OSI模型中最高的三层相对应。

TCP/IP协议族中的各层包含了一些相对独立的协议。在物理层和数据链路层,TCP/IP并没有定义任何协议。在网络层TCP/IP支持网际互联协议(IP),而IP又由四个支撑协议组成:ARP、RARP、ICMP和IGMP。在传统上,TCP/IP协议族在运输层有两个运输协议:TCP和UDP,然而现在已经设计出一个新的运输层协议SCTP以满足新的应用的需要。IP是主机到主机的协议,即把分组从一个物理设备交付到另一个物理设备。UDP和TCP是运输机协议,负责把报文从一个进程(运行着的程序)交付到另一个进程。

1.2 编址

使用TCP/IP协议的互联网使用3个等级的地址:物理(链路)地址、逻辑(IP)地址以及端口地址。每一种地址属于TCP/IP体系结构中的特定层。

1.2.1 物理地址

物理地址也叫链路地址,是结点的地址,由它所在的局域网或广域网定义。物理地址包含在数据链路层使用的帧中。

以太网的地址是6字节(48位)长,通常用十六进制记法,如:07:01:02:01:2C:4B。以太网的地址共3种:单播、多播和广播。在单播地址中的第一个字节的最低位0;在多播地址中的第一个字节的最低位是1。广播地址是48个1。

1.2.2 逻辑地址

因特网的逻辑地址是32位地址,可以用来标志连接在因特网上的每个主机。在因特网上没有两个主机有相同的IP地址。同样,逻辑地址也可以是单播地址、多播地址和广播地址。

Internet被各种路由器和网关设备分隔成很多网段,为了标识不同的网段,需要把32位的IP地址划分成网络号和主机号两部分,网络号相同的各主机位于同一网段,相互间可以直接通信,网络号不同的主机之间通信则需要通过路由器转发。把所有IP地址分为五类,如下图1所示:


A类 0.0.0.0到127.255.255.255
B类 128.0.0.0到191.255.255.255
C类 192.0.0.0到223.255.255.255
D类 224.0.0.0到239.255.255.255
E类 240.0.0.0到247.255.255.255

在分类编址的A类、B类、C类地址中,IP地址可划分为net-id(网络标识)和host-id(主机标识)。对于A类地址,1字节定义net-id而3字节定义host-id。对于B类地址,2字节定义net-id,2字节定义host-id。对于C类地址,3字节定义net-id而1字节定义host-id。D类地址和E类地址不划分net-id和host-id。

网络地址是一个地址块的第一个地址,向因特网的其余部分定义这个网络。路由器就是根据网络地址来选择分组的路由。若给出网络地址,我们就能够找出这个地址的类别、地址块以及这个地址块的地址范围。

这种划分方案有很大的局限性,它对网络的划分是flat的而不是层级结构(hierarchical)的。Internet上的每个路由器都必须掌握所有网络的信息,随着大量C类网络的出现,路由器需要检索的路由表越来越庞大,负担越来越重。

于是提出了新的划分方案,称为CIDR(Classless Interdomain Routing)。网络号和主机号的划分需要用一个额外的子网掩码(subnet mask)来表示,而不能由IP地址本身的数值决定,也就是说,网络号和主机号的划分与这个IP地址是A类、B类还是C类无关,因此称为Classless的。这样,多个子网就可以汇总(summarize)成一个Internet上的网络。

IP地址与子网掩码做与运算可以得到网络号,主机号从全0到全1就是子网的地址范围。IP地址和子网掩码还有一种更简洁的表示方法,例如140.252.20.68/24,表示IP地址为140.252.20.68,子网掩码的24位是1,也就是255.255.255.0。

目的地址为255.255.255.255,表示本网络内部广播,路由器不转发这样的广播数据包。目的地址的主机号为全1,表示广播至某个网络的所有主机,例如目的地址192.168.10.255表示广播至192.168.10.0网络(假设子网掩码为255.255.255.0)。

1.2.3 端口地址

计算机是多进程设备,即可以在同一时间运行多个进程。因特网通信的最终目的是使一个进程能够和另一个进程通信。为了能够同时发生这些事情,需要有一种方法对不同的进程打上标号,就是说这些进程需要地址。

在TCP/IP体系结构中,给一个进程指派的标号叫做端口地址。TCP/IP中的端口地址是16位长,通常用10进制数表示。

1.3 分层数据包介绍

1.3.1 以太网帧


目的地址(DA)   DA字段有6字节,是下一站的物理地址(也叫MAC地址)。

源地址(SA)     SA字段有6字节,是前一站的物理地址。

类型             类型字段有三种值,分别对应IP、ARP、RARP。

数据             携带从上层协议封装起来的数据。它的最小长度是46字节,最大长度是1500字节。ARP、RARP的数据包长度不够   46字节,要在后面补填充位。最大值1500称为以太网的最大传输单元(MTU),如果一个数据包从以太网路由到链    路上,数据包的长度大于链路的MTU了,则需要对数据包进行分片

CRC            差错检测信息,4字节。

1.3.2 ARP报文格式


硬件类型           16位字段,用来定义运行ARP的链路层网络的类型。以太网是类型1。

协议类型           16位字段,指要转换的地址类型。0x0800位IP地址。

硬件长度           8位字段,定义以字节为单位的物理地址长度。对以太网这个值为6。

协议长度           8位字段,定义以字节为单位的逻辑地址长度。对IPv4协议这个值是4。

操作               16位字段,定义分组的类型。为1表示ARP请求,为2表示ARP应答。

发送端硬件地址     可变长度字段,定义发送端的物理地址。

发送端协议地址     定义发送端的逻辑地址。

目标硬件地址       定义目标的物理地址。对于ARP请求报文,这个字段是0,因为发送端不知道目标的物理地址。

目标协议地址       定义目标的逻辑(如,IP)地址。

1.3.3 IP数据报文格式
版本(VER)       这个4位字段定义IP协议的版本。

首部长度(HLEN)   这个4位字段定义IP首部总长度,以4字节为单位计算。当没有选项时,首部长度是20字节,这个字段的值是  5(5*4=20)。当选项字段位最大值时,这个字段的值是15(15*4=60)。

服务类型(DS)     TOS位是4位子字段,共有5种不同的服务类型。

总长度             这个16位字段定义了以字节计的数据报总长度(首部加上数据)。要找出上层传来的数据长度,可以从总长度减去首部长度。总长度字段是16位,因此IP数据报的长度限制是65535(216 - 1)字节。

标识(Identification)   这个16位字段与源IP地址一起唯一地定义这个数据报。IP协议使用一个计数器来标志数据报,当IP协议发送数据时,就把这个计数器的当前值复制到标识字段中,并加1。当数据报被分片时,标识字段的值就复制到所有的分片中。换言之,所有的分片具有相同的标识号,即原始数据报的标识号。在终点重装数据报时,终点就知道所有具有相同标识号的分片必须组装成一个数据报。

标志(Flags)       3位字段。第一位保留。第二位为不分片位,为1表示不对数据报进行分片;为0表示在需要时对数据报进行分      片。第三位为分片位,为1表示这个数据报不是最后的分片,在其后还有分片;为0表示这个数据报是最后的分      片。

分片偏移(FragmentOffset)       这个13位字段表示该分片在整个数据报中的相对位置,以8字节为度量单位。

生存时间(TTL)    用来控制数据报所通过的最大路由跳数,这个生存时间的单位不是秒,而是(hop)。

协议               这个8位字段定义使用IP层服务的高层协议。如:TCP、UDP、ICMP和IGMP等。

检验和             IP分组中的检验和只在首部而不在数据部分进行。因为,所有将数据封装在IP数据报中的高层协议,都有覆盖整个分组的检验和;其次,,每经过一个路由器,IP数据报的首部就要改变一次,但数据部分不变。因此检验和只对发生变化的部分进行检验。

源地址             这个32位字段定义源点的IP地址。在IP数据报从源主机发送到目的主机的时间内,这个字段必须保持不变。

目的地址           这个32位字段定义了终点的IP地址。在IP数据报从源主机发送到目的主机的时间内,这个字段必须保持不变。

1.3.4 ICMP报文格式

类型               8位字段,定义ICMP报文的类型。ICMP报文的类型有:终点不可达、源点抑制、超时、参数问题、改变路由、回送请求或回答、时间戳请求或回答、地址掩码请求或回答、路由器询问和通告。

代码               8位字段,指明了发送这个特定报文类型的原因。

检验和(icmpchksum)  16位字段。在ICMP中,检验和的计算覆盖了整个报文(首部和数据)。

ICMP回送请求或回答报文头格式如下图所示:


ICMP终点不可达报文头格式如下图所示:


ICMP超时报文头格式如下图所示:



1.3.5 IGMP报文格式

类型            8位字段,定义了查询、成员关系报告、退出报告三种报文类型,类型值分别为0x11、0x16、0x17。最大响应时间8位字段,定义了查询必须在多长时间内回答。它的值以十分之一秒位单位。在查询报文中这个值不是零,但在其他两种报文中则置为零。

检验和        16位字段,检验和在8字节的报文上计算。

组地址         在一般查询报文中这个字段的值为0,在特殊查询报文、成员关系报告报文以及退出报告报文中定义groupid(组多播地址)。


1.3.6 UDP用户数据报首部格式

UDP数据报格式如上图所示。

用户数据报有8个字节的固定首部。

源端口号        16位字段,定义源主机上运行的进程所使用的端口号。

目的端口号    16位字段,定义目的主机上运行的进程使用的端口号。

长度               16位字段,定义了用户数据报的总长度,首部加上数据。

检验和            16位字段,UDP的检验和包括三部分:伪首部、UDP首部以及从应用层来的数据。位首部是IP分组的首部的一部分,包括:源IP地址、目的IP地址、8位协议和16位UDP总长度。位首部可以保证在IP首部受到损伤时,用户数据报可以交付到正确的主机。协议字段的加入,可以确保这个分组是属于UDP而不是属于TCP。

1.3.7 TCP报文段格式

如上图所示,TCP报文段的结构包括:

源端口地址         这个16位字段定义发送报文段的应用程序端口号。

目的端口地址       这个16位字段定义了接收该报文段的应用程序端口号。

序号               这个32位字段定义了指派给本报文段第一个数据字节的一个号。为了保证连通性,要发送的每一个字节都要编号。序号告诉终点,这个序列中的哪一个字节是报文段中的第一个字节。在连接建立时,每一方使用随机数产生器产生初始序号(ISN)。

确认号             32位字段,定义了报文段接收端期望从对方接收的下一个序号。如果报文段的接收端成功地发送了对方发来的序号x,它就把确认号定义为x+1。

首部长度(tcpoffset)   4位字段,指出TCP首部共有多少个4字节字。即TCP数据在IP数据中的偏移大小。同IP首部长度,可以在5 至15之间。

保留位             该6位字段留待今后使用。

控制/标志位        该字段定义了6种不同的控制位或标志,在同一时间可设置一位或多位标志。



窗口值             该字段定义接收方必须维持的窗口值(以字节为单位)。注意,该字段是16位长,因此窗口值的最大长度为65535字节。这个值由接收端来确定,发送端必须服从接收端的决定。

检验和             这个16位字段包含检验和,TCP使用检验和是强制性的。

紧急指针          当紧急标志位置位时,这个16位字段才有效,这时的报文段中包括紧急数据。紧急指针定义了一个数,把这个数加到序号上就得出报文段数据部分中最后一个紧急字节。

选项               包括无操作(NOP)、最大报文段长度(MSS)、窗口扩大因子、时间戳等。


1.4 分层协议讲解

总的来说,TCP/IP协议的多路选择过程可以表示为下图:



1.4.1 ARP和RARP
1.4.1.1 地址解析协议ARP

在任何时候,当主机或路由器有数据报要发送给另一个主机或路由器时,它必须有接收端的逻辑(IP)地址。但是IP数据报必须封装成帧才能通过物理网络。这就表示,发送端必须有接收端的物理地址,因此需要有从逻辑地址到物理地址的映射。

地址解析协议(ARP)用来把IP 地址与其物理地址联系起来。任何时候当主机或路由器需要找出这个网络上的另一个主机或路由器的物理地址时,它就发送ARP查询分组。这个分组包括发送端的物理地址和IP地址,以及接收端的IP地址。

因为发送端不知道接收端的物理地址,查询就在网络上广播。例如,数据包要发送给IP地址为192.168.0.1的主机,过程如下:

源主机发出ARP请求,询问“IP地址是192.168.0.1的主机的硬件地址是多少”,并将这个请求广播到本地网段(以太网帧首部的硬件地址填FF:FF:FF:FF:FF:FF表示广播),目的主机接收到广播的ARP请求,发现其中的IP地址与本机相符,则发送一个ARP应答数据包给源主机,将自己的硬件地址填写在应答包中。

ARP报文格式如前所述。

ARP软件包由5个构件组成:

    高速缓存表:

    每台主机都维护一个ARP高速缓存表,由于高速缓存表的空间非常有限,所以缓存表中的表项有过期时间(一般为20分钟),如果20分钟内没有再次使用某个表项,则该表项失效,下次还要发ARP请求来获得目的主机的硬件地址。

    队列:

    队列用来在ARP试图解析硬件地址时保留IP分组。输出模块把未解析的分组发送到相应的队列,输入模块从一个队列中拿走一个分组,并连同解析出的物理地址一同发送给数据链路层来传输。

    输出模块:

    输出模块从IP软件等待IP分组。输出模块检查高速缓存表,寻找是否有某个项目对应于这个分组的目的IP地址。这个IP分组的目的IP地址必须与这个项目的协议地址相匹配。

    输入模块:

    输入模块一直等待,直到有ARP分组到达。检查高速缓存表,寻找对应这个ARP分组的项目。输入模块设置这个项目的超时时间TIME-OUT。若队列为空,则从相应队列中把分组一个接一个地取出,连同其硬件地址一起交给数据链路层来处理。

    高速缓存控制模块:

    负责维护高速缓存表,它周期性地逐项检查高速缓存表,判断有哪些项目到期,哪些队列需要撤销。

1.4.1.2 逆地址解析协议RARP

 当一个主机知道自己的物理地址时,RARP可用来找出其逻辑地址。每一个主机或路由器都被指派一个或多个逻辑地址,这些地址与机器的物理地址无关。要创建IP数据报,主机或路由器要知道它自己的IP地址。可以使用RARP协议从物理地址得到逻辑地址。

     知道物理地址后,先创建RARP请求,并在本地网络上广播。在本地网络上的另一个机器知道所有的IP地址,它就用RARP回答来响应。请求的机器必须运行RARP客户程序;而响应的机器必须运行RARP服务器程序。

1.4.2 IP协议

IP数据报的格式如前所述。

IP是不可靠的无连接协议,负责源点到终点的交付。

在IP层的分组叫做数据报。

数据链路层有自己的帧格式,在这个格式中有一个字段是“数据字段最大长度”。当数据报封装成帧时,数据报的总长度必须小于这个数据字段最大长度(MTU)。

对数据报进行分割,叫做分片。源站通常不对IP分组进行分片。运输层会进行分片工作,把数据划分成IP和在使用的数据链路层都可能接纳的大小。数据报在到达终点之前可以经过多次分片,可以被源主机或在其路径上任何路由器进行分片。然而数据报的重组却只能在目的主机上进行。

在IP分组中的检验和只在首部而不在数据部分心进行。因为,首先所有将数据封装在IP数据报中的高层协议,都有覆盖整个分组的检验和;其次,每经过一个路由器,IP数据报的首部就要改变一次,但数据部分不变。因此检验和只对发生变化的部分进行检验。 

IP软件包包括8个构件:首部添加模块、处理模块、转发模块、分片模块、重装模块、路由表、MTU表以及重装表,还有输入和输出队列。

首部添加模块,从高层协议接收数据(连同其IP地址),添加IP首部后,把数据封装成IP数据报。

处理模块,从一个接口或从首部添加模块接收数据报,首先检查数据报是否为回环地址,还是这个分组已到达最后终点。

输入队列把从数据链路层或从高层协议发来的数据存放起来。

输出队列把要发送到数据链路层或高层协议的数据报存放起来,处理模块从中取出数据报,分片和重装模块则把这个数据报加入输出队列中。

路由表是在转发模块中使用的,用来确定分组的下一跳地址。

分片模块从转发模块接收IP数据报。转发模块给出IP数据报、下一站的IP地址。以及发送这个数据报所必须通过的接口号。分片模块使用MTU表以便找出对于特定接口的最大传送单元MTU。若数据报的长度大于MTU,则分片模块对数据报进行分片,为每一个分片添加首部,并把它们发送到ARP软件包进行地址解析和交付。

重装模块从处理模块接收已到达最终目的地的数据报分片。重装模块将未分片的数据报看成是属于仅有一个分片的数据报。使用重装表找出一个分片是属于哪一个数据报,将属于同一个数据报的各分片进行排序,并在所有分片到达时把它们重新组装成一个数据报。

1.4.3 ICMP协议

IP协议没有差错报告或差错纠正机制和管理查询机制。网际控制报文协议(ICMP)就是为了补偿这两个缺点而设计的。它是配合IP协议使用的。

CMP本身是网络层协议,但是它的报文不是如设想的那样直接传送给数据链路层,而是首先要封装成IP数据报,再传送给下一层。

在IP数据报中的协议字段值是1就表示其IP数据是ICMP报文。

ICMP报文类型如下表2-2所示:




1.4.4 IGMP协议

网际组管理协议(IGMP)是与多播有关的一个必要的但不是充分的协议。IGMP并不是多播路由选择协议,而是个管理组成员关系的协议。每当主机需要加入或离开某个特定的多播群组时,该协议允许该主机去通知邻近的路由器。

该协议只用在主机与路由器之间的网络上。而且,协议只把计算机(不是应用进程)定义为群组成员。

如果在一个给定计算机上有多个进程要加入到一个多播群组,计算机必须要把接收到的每个数据报复制多个副本给每个进程。只有当最后一个进程离开群组时,计算机才利用IGMP通知本地的路由器,表明它不再是群组的成员了。IGMPv2有3种报文类型:查询、成员关系报告和退出报告。

IGMP可分为两个阶段:

第一阶段:当某个主机加入新的多播组时,该主机应向组播组的多播地址发送一个IGMP报文,声明自己要成为该组的成员。本地的多播路由器收到IGMP报文后,将组成员关系转发给因特网上的其他多播路由器。

第二阶段:因为组成员关系是动态的,因此本地多播路由器要周期性地探询本地局域网上的主机,以便知道这些主机是否还连续是组的成员。只要对某个组有一个主机响应,那么多播路由器就认为这个组是活跃的。但一个组在经过多次的探询后仍然没有一个主机响应,则多播路由器就认为本网络上的主机已经都离开这个组了因此就不再将该组的成员关系转发给其他的多播路由器。

IGMP报文格式如前所述。

IGMP协议的优点:

1. 主机和多播路由器的所有通信使用IP多播,只要有可能,携带IGMP报文的数据报都使用硬件多播来传送。

2. 多播路由器在探询组成员关系时,只需要对所有多播组只发一个查询,而不是对每一个组发送一个查询,默认125S一次。

1.4.5 UDP协议

UDP数据报的格式如前所述。

UDP位于应用层和IP层之间,作为应用程序和网络操作的中介物。

IP是负责在计算机级的通信(主机到主机的通信),作为网络层协议,IP只能把报文交付给目的主机。但是,这是一种不完整的交付。这个报文还必须送交到正确的进程。UDP就是负责把报文交付给适当的进程。

完成进程到进程的通信最常用的方法是通过客户-服务器范例。在本地主机上叫做客户的进程主动发起请求, 远程主机上叫做服务器的进程被动地等待、接收和应答请求。客户端的IP地址和端口号唯一标识了该主机上的客户端进程,服务器的IP地址和端口号唯一标识了该主机上的服务端进。由于客户端是主动发起请求的一方,它必须知道服务器的IP地址和服务进程的端口号,所以,一些常见的网络协议有默认的服务器端口。TCP/IP协议族中,端口号是在0~65535之间的整数。ICANN把端口号划分为3个范围:熟知端口号、注册端口号和动态(或专用)端口号。

熟知端口范围从0~1023;注册端口范围从1024~49151;动态端口范围从49152~65535.

已知UDP需要两个标识符,即IP地址和端口号,各用在一端以建立一条连接。一个IP地址和一个端口号合起来叫做套接字地址。这些信息是IP首部和UDP首部的一部分。

UDP提供物连接服务,即UDP发出的每一个用户数据报都是独立的数据报,每一个用户数据报可以走不同的路径到达目的进行。UDP缺少流量控制和差错控制。

要从一个进程把报文发送到另一个进程,UDP协议就要把报文进行封装和拆装。

1. 封装

当进程有报文要通过UDP发送时,它就把这个报文连同一对套接字地址以及数据的长度传递给UDP,加上UDP首部后,UDP把用户数据报连同套接字地址一起传递给IP。IP加上自己的首部,在协议字段使用值17,指出该数据是从UDP协议来的。再将IP数据报传递给数据链路层,数据链路层收到IP数据报后,再加上自己的首部传递给物理层。物理层将这些位编码为电信号或光信号,把它发送到远程机器。

2.拆装

报文到达目的主机时,物理层对信号解码,将它变为位,传递给数据链路层。数据链路层使用这个首部(和尾部)检查数据。若无差错,则去掉首部和尾部,并把数据报传递给IP。IP软件进行检查,若无差错,就剥去首部,把用户数据报连同发送端和接收端的IP地址一起传递给UDP。UDP使用检验和对整个用户数据报进行检查。若无差错则剥去首部,把应用数据传递给接收进程。在需要回答收到的报文时,应把发送端的套接字地址一起传递给接收进程。

     UDP软件包共包括5个构件:一个控制块表、若干个输入队列、一个控制块模块、一个输入模块和一个输出模块。在UDP中,队列是与端口相关联在一起的。这里的实现只创建与每一个进程相关联的输入队列,而不创建输出队列。

3. 控制块表

UDP控制块表来记录打开的端口。表中的每一个项目有最小的4个字段:状态(FREE或IN-USE)、进程ID、端口号以及相应的队列号。

4.  输入队列

使用了一组输入队列,每一个对应于一个进程。

5. 控制块模块

负责管理控制块表。当进程启动时,它就从操作系统请求得到一个端口号。操作系统把熟知端口号指派给服务器,而把短暂端口号指派给客户。进程把进程ID和端口号传递给控制块模块,以便在表中为这个进程创建一个项目。这个模块不创建队列。队列数字段值为零。

6.  输入模块

输入模块从IP接收用户数据报。它查找控制块表,查找具有和这个用户数据报同样端口号的项目。若找到这样的项目,模块就利用这项目中的信息把这个数据放入队列。若未找到这样的项目,它就产生ICMP“端口不可达”报文,并丢弃这个项目。

7. 输出模块

负责创建和发送用户数据报。

1.4.6 TCP协议

TCP叫做面向连接的、可靠的运输协议。它提供进程到进程、全双工和面向连接的服务。TCP使用滑动窗口机制实现流量控制,来避免接收端因数据过多而过载;使用差错控制来提供可靠的服务。

两个设备之间使用TCP软件传送的数据单元叫做报文段,它有20~60字节的首部,首部后面是来自应用程序的数据。首部结构如前所述。

1.4.6.1 TCP连接

TCP的连接通常包括3个阶段:连接建立、数据传送和连接终止。

连接建立需要三向握手

1. 客户发送第一个报文段,SYN报文段,在这个报文段中只有SYN标志位置1.这个报文段的作用是使序号同步。SYN报文段是控制报文段,不携带任何数据,但是消耗一个序号。当数据传送开始时,每发送一个字节,序号应该加1. 在接收端可以根据序号排出数据包的正确顺序,也可以发现丢包的情况。

2. 服务器发送第二个报文段,SYN+ACK报文段,有两个标志位置1(SYN和ACK)。服务器使用这个报文段同步初始序号,以便从服务器向客户发送字节。使用ACK确认已从客户端收到了SYN报文段,确认号为客户端发送SYN报文段序号值加1.

3.  客户发送第三个报文ACK,确认号为服务器发送报文段的序号值加1。该报文段的序号与SYN报文段使用的序号一样。

ACK报文段如果不携带数据就不消耗序号。

连接建立后,数据开始双向传送

在数据传输过程中,ACK和确认序号是非常重要的,应用程序交给TCP协议发送的数据会暂存在TCP层的发送缓冲区中,发出数据包给对方之后,只有收到对方应答的ACK段才知道该数据包确实发到了对方,可以从发送缓冲区中释放掉了,如果因为网络故障丢失了数据包或者丢失了对方发回的ACK段,经过等待超时后TCP协议自动将发送缓冲区中的数据包重发。

     以上情况只描述了最简单的一问一答的情景,事实上TCP协议为应用层提供了全双工(full-duplex)的服务,双方都可以主动甚至同时给对方发送数据。如果通讯过程只能采用一问一答的方式,收和发两个方向不能同时传输,在同一时间只允许一个方向的数据传输,则称为'''半双工(half-duplex)''',假设某种面向连接的协议是半双工的,则只需要一套序号就够了,不需要通讯双方各自维护一套序号了。 

参加交换数据的双方中的任何一方都可以关闭连接, 连接终止的四向握手

1. 在正常情况下,客户机TCP接收到客户进程发来的关闭命令后,就发送第一个报文段——把FIN位置1。如果FIN报文段不携带数据,它消耗一个序号。同时更改状态为FIN_WAIT_1,关闭应用程序进程。

2. 服务器TCP在收到这个FIN报文段后,向自己对应的进程发送一个文件结束符EOF,同时更改状态为CLOSE_WAIT,并发送第二个报文段——ACK,以证实从客户端收到了FIN报文段。如果不携带数据,客户端接到ACK后状态更改为FIN_WAIT_2。

3. 服务器关闭应用程序进程,更改状态为LAST_ACK。并发送第三个报文段——FIN,若不携带数据,FIN消耗一个序号。

4.  客户TCP接收到FIN后,更改状态为TIME-WAIT,同时发送最后一个报文段——ACK,证实从TCP服务器收到了一个FIN报文段,该报文段的确认号等于从服务器发送的FIN报文段的序号加1 。

除上述的情况外,建立连接时,客户端和服务器端可以同时打开;关闭连接时,可以同时关闭或者进行三向握手。

TCP的状态机转换图如下所示:

TCP的各种状态如下表2所示:



0 0