从通信和信息处理两方面来看,“传输层”既是面向通信部分的最高层,与下面的三层一起共同构建进行网络通信所需的线路和数据传输通道,同时又是面向用户的最低层,因为无论何种网络应用,最终都需要把各种数据报传送到对方。来自应用层的用户数据必须依靠传输层协议在不同网络中的主机间进行传输,因为仅靠网络层把数据传送到目的主机上还是不够的,还必须把它交给目的主机的应用进程。
物理层为数据通信提供实际的物理线路和通信信道,这是任何数据通信的基础;数据链路层为同一网络中(数据链路层的通信限于同一局域网中)的数据通信提供了虚拟的通信通道,可以根据不同链路类型对物理层的比特流进行帧封装和传输;网络层为不同网络间的数据通信提供了数据包的路由、转发功能,把数据包从一个网络中的主机传送到位于另一网络中的目的主机上,其中需要选择传送的最佳路径。
既然网络层已把源主机上发出的数据包传送给了目的主机,那么为什么还需要设置一个传输层呢?
位于两台网络主机间的真正数据通信主体不是这两台主机,而是两台主机中的各种网络应用进程。因为在同一时刻,两主机间可以进行多个应用通信。 而这里的应用进程识别就要依靠“传输层”了,它就是通过“端口”将不同应用进程进行对应的。
“传输层”是源端到目的端对数据传送进行控制的从低到高的最后一层,最终目标就是向它的用户(应用层中的应用进程)提供高效、可靠和性价比合理的服务。
在传输层内部,完成这项任务的硬件或软件称为传输实体(transport entity)。传输实体可能位于操作系统的内核,或者在一个独立的用户进程中,或者以一个链接库的形式被绑定在具体的网络应用中。
(其中的TPDU为传输协议数据单元)
传输层的主要作用就是为它的上层提供端到端的数据传输服务。
第一层含义是从物理的网络连接角度来讲的,即端到端是指网络通信的双方不是在同一链路上,不是点对点连接的;
第二层含义是从虚拟的传输连接角度来讲的,即端到端是指在用户看来两端的连接是直接进行的(其实并不是这样的),屏蔽了核心网络结构和各种子网间的差异。
(1)“点对点”连接就是通信双方直接通过电缆进行的连接,中间没有经过任何其他设备。
如 路由器R1与主机A、R2与主机B、R3与主机C这三对之间的连接,以及R与R2、R1与R3、R2与R3这三对之间的连接
“点对点”传输:源端可直接把数据传给与它直接相连的设备,在需要的时候又可把数据传给与之直接相连的下一台设备,通过一台台直接相连的设备,把数据传到接收端。很显然,这是一种接力传输方式,但是不可靠。
(2)“端到端”连接是两个终端系统之间的连接,体现在两个终端系统的连接中时要经过一个或多个设备。
如 主机A与主机B、主机C与主机A、主机B与主机C这三对之间的连接
“端到端”传输:需要在两端所经过的线路上建立一条构建于网络层已搭建好的路由路径之上的虚拟传输连接(当然,这里仅是针对面向连接的传输层协议而讲的),以此来屏蔽所经网络类型或参数配置的不同,就像它们是直接相连的一样;链路建立后,源端就可以发送数据,直至数据发送完毕,接收端确认接收成功。
直到目的端收到数据为止,源端的设备一直要参与传输,因为只有在传输完成后,从源端到目的端所建立的虚拟传输连接才能“拆除”,否则会中途中断数据的传输,因此是可靠传输。
在一个网络系统的不同层次中,可能用到端到端传输,也可能用到点到点传输。
例如在Internet中,网络层及以下各层都采用点对点传输,传输层以上采用端到端传输。
如两个应用进程通信时,两个进程要一直参与传输过程,而进程下面的网络层、数据链路层等,只需要将上层的数据传给与它直接相连的设备即可。
“传输层”在通信子网提供的服务基础上,为源主机和目的主机之间提供可靠的、透明的、可由用户选择的数据传输服务,是面向用户的高层和面向通信子网的低层之间的软件接口,或者称为“桥梁”。同时,传输层也弥补了高层所要求的可靠、可控制服务与网络层所提供的非可靠服务之间的差距,并向高层屏蔽通信子网中不同网段的差异。
(1)面向连接服务
在提供传输服务前需要先建立专门的传输连接,而且这条连接是可管理的,在需要或通信结束时进行拆除。面向连接的传输服务是可靠的传输服务,而且可提供拥塞控制和差错控制功能,如TCP提供的传输服务。
(2)无连接服务
在提供服务前不需要建立专门的传输连接,直接向目的节点发送数据,不管是否有可传输的通道,只提供不可靠(仅做尽力传输)的传输服务,如UDP提供的传输服务。
上述服务与网络层提供的面向连接和无连接服务很像,但网络层是通信子网的一个组成部分,网络服务质量并不可靠,如频繁地丢失分组,网络层系统可能崩溃或不断地进行网络复位。对于这些情况,用户将束手无策,因为用户不能对通信子网加以控制。而传输层能对通信子网进行管理和控制。
不同类型的网络,以及不同连接性能的网络,所提供的传输层服务级别也不一样。
(1)传输层提供的服务可分为“传输连接”服务和“数据传输”服务。
“传输连接”服务是传输层为它的上层发出的每个应用进程在网络层提供的服务基础之上建立一个相应的逻辑连接;
“数据传输”服务则是在所建立的传输连接基础上,为用户提供比网络层更有保障(主要针对面向对用户的传输层服务而言)、更有针对性,并且能由用户自己进行拥塞控制、差错控制的数据传输。
(2)根据不同网络所提供的不同传输层服务质量水平,可把传输层服务分为以下三大类。
❏A类:具有低的连接差错率和故障率,是可靠的传输服务,一般指在虚电路网络上。
❏B类:具有较低的连接差错率和故障率,传输服务质量中等,应用于广域网和互联网中的传输层协议多数属于这一类。
❏C类:具有较高的连接差错率和故障率,服务质量较差,提供数据报服务或无线电分组交换网所提供的传输层协议均属此类。
在OSI/RM体系结构的传输层中,不同类型的传输层协议所支持的服务级别不一样,共分TP0~TP4五种类型。
在OSI/RM体系结构的传输层中,涉及两个非常重要的术语—TSAP(传输服务访问点)和TPDU(传输协议数据单元),它们贯穿整个传输层数据传输服务的始末。
TSAP是上层调用传输层服务,以及传输层为它的上层提供服务的逻辑接口。
同一时间、同一对网络实体间的用户应用进程可能有多个,不能仅靠网络实体地址(即NSAP)来标注通信双方(因为此时通信的实体是各个应用进程,而不是通信双方主机),而必须借助传输层地址进行标识。TSAP相当于传输层的地址,不同的TSAP标识不同的会话或应用进程。
为确保所有的传输地址在整个网络中是唯一的,因此将传输地址分成网络ID、主机ID、主机分配的端口三部分。
“端口”是传输层特定的属性,用来与应用进程进行一一对应的,所以说真正的传输层地址其实就是具体应用所占用的“端口”。
传输层的数据单元是“数据段”,这个名称显然太容易混淆,于是在OSI/RM体系结构的传输层中还是把其中传输的数据单元称为TPDU(不过,在TCP/IP体系结构中,TCP的协议数据单元仍然为“数据段”)。
其实,TPDU与本书前面几章中介绍的“比特”、“帧”“分组”(或“包”)是同类概念。
❏LI:占1字节,以字节为单位标识整个TPDU头部的长度,最大值为254。
❏固定部分:包括TPDU代码和常用参数,其内容对于某一特定的TPDU来说是固定的,如包括目的端口和源端口等,但是不同传输层协议的TPDU是不一样的。
❏可变部分:包含一些可选参数项,每个参数项由三个字段构成:Code(代码,1字节)、Length(长度,1字节)和Value(值,长度可变),也就是通常所说TLV。
❏有效载荷:包含上层的用户数据
OSI/RM体系结构中常见TPDU的类型:
在传输连接建立阶段,主要用到了CR(连接请求)TPDU和CC(连接确认)TPDU两种。
❏代码:标识TPDU类型,占4位,CR TPDU的代码值为1110,CC TPDU的代码值为1101
❏CDT:信用量分配,表示能接收的TPDU序号的上限值(暗示了可接收的TPDU数量),占4位。CDT类似于后面在介绍TCP数据段格式中所说到的“窗口大小”字段,对端通过对CDT字段值的识别以改变当前的发送窗口大小。
❏目的参考:指该传输连接的目的端对等传输实体用来唯一标识这一连接的标识符,也就是对端传输连接序号,占16位。CR TPDU中的“目的参考”为全0,因为连接尚未建立(正在请求中),将由目的端选择。
❏源参考:本地传输连接标识符,也就是本地传输连接的序列号,占16位。
❏类别选项:占8位,高4位标识使用的传输层协议类型(TP0~TP4);低4位是可选项,用来说明在DATA TPDU和AK TPDU中的序号字段是正常的,还是扩展的,正常为0000,扩展为0010。
通常TPDU序号只有7位,但对于TP2~TP4传输层协议来说,序号可以扩展到32位。
在传输连接建立阶段,主要用到了DT(数据)TPDU、AK(数据确认)TPDU、ED(加速数据)TPDU和EA(加速数据确认)TPDU四种。
这里要特别注意,在所有TPDU中,只有DT TPDU和ED TPDU才有“TPDU序列号”字段,也就是只有这两种TPDU才会进行编号,其他TPDU均不编号
另外,只有AK TPDU和EA TPDU才有“你的序列号”字段,其他TPDU均没有该字段。
(1)当选择TP0和TP1类型传输协议(不支持多路复用)时,它的格式如图
TPDU序列号和EOT:占8位,高7位标识对应DT TPDU的序列号;最低位(EOT位)用来标识此TPDU是否是某个数据的最后一个数据段,等于1时表示是最后一个数据段。
(2)当选择TP2、TP3和TP4类型传输协议(支持多路复用)时,它的格式要分两种情况:
一是在建立传输连接时选择的不是TP2~TP4类型,此时DT TPDU格式如图
二是在建立传输连接时也选择的是TP2~TP4类型,此时DT TPDU格式如图。
因为TP2~TP4类传输层协议支持多路复用,需要标识各传输连接号,所以需要“目的参考”这个字段,而TP0~TP1类型传输层协议是不支持多路传输连接复用的,所以即使在传输数据时不标识传输连接号,也不会出现差错。
你的TPDU序列号(YR-TU-NR, Your-TPDU-Number),将在后面简写为YR-TU-NR
格式同 DT TPDU
对比AK TPDU,EA TPDU中只是少了CDT字段,因为加速数据的发送是不按TPDU顺序号发送的,有加速数据就立即发送,是数据传输过程中的少数特例
在连接释放阶段主要的TPDU分为DR TPDU(断开连接请求)和DC TPDU(断开连接确认)两种
“服务原语”(service primitive)是服务功能实现的具体过程描述,也就是要完成一项服务,必须要经过哪些主要步骤。一个服务通常由一组原语操作来描述,用户进程通过这些原语操作可以访问该服务。这些原语告诉该服务执行某个动作,或者将某个实体所执行的动作报告给用户。如果协议栈位于操作系统中(大多数情况是这样的),则这些服务原语通常是一些系统调用。这些系统调用会进入到内核模式,然后在内核模式中控制该机器,让操作系统发送必要的分组。
到底哪些原语可以使用则取决于所提供的服务,针对面向连接的服务的原语与针对无连接的服务的原语是不同的。
1)一开始,服务器调用Listen原语,使其处于监听状态,直到有客户来请求连接。
2)当一个客户希望与该服务器进行会话时,它调用Connect原语,向服务器发送一个请求建立传输连接的CR TPDU。
3)当该CR TPDU到达服务器时,服务器传输服务实体执行状态检查,看服务器是否正处于监听状态。如果是,则解除监听,并向客户端返回一条确认连接请求的CC TPDU。
4)在这个CC TPDU到达客户端后,客户端获知服务器同意建立传输连接了,随后便通知客户端应用进程开始建立传输连接。
5)传输连接建议好后,就可以正式发送DT TPDU了。任何一方都可以调用Receive原语,以等待另一方调用Send原语,发送数据。当一方接收到另一方发来的DT TPDU时,接收端会发送一个数据接收确认的DA TPDU。
6)当不再需要一个连接时,传输用户必须将它释放,以便使两个传输实体内部的缓存空间有机会被重新使用。
释放连接有两种形式:
(1)对称释放: 连接的两个方向彼此独立,每个方向需要单独被释放。当一方调用Disconnect原语时,意味着它不再需要发送数据了,但它仍然希望能接收对方发过来的数据。在这种方式中,只有在双方都调用了Disconnect原语,各自向对方发送DR TPDU后一个传输连接才可能被真正释放出来。
(2)非对称释放: 任何一方都可以调用Disconnect原语,在本端传输实体向对端发送一个DR TPDU后双向传输连接都将被释放。
2.ISO规范中的传输服务原语
❏请求(request):用户利用它要求服务提供者提供某项服务,如建立连接或发送数据等。
❏指示(indication):服务提供者执行请求原语后,用指示原语通知本端用户实体,告知有人想要与之建立连接或发送数据等。
❏响应(response):收到指示原语后,利用响应原语向对方做出反应,如同意或不同意建立连接等。
❏确认(confirm):请求方可以通过接收确认原语来获悉对方是否同意接受请求。
在OSI/RM体系结构的传输层中,面向连接服务主要包括10种传输服务原语,分布在传输连接建立、数据发送和传输连接断开这3个主要阶段中。
无连接服务原语只有两个:
部分参数详解:
“主叫地址”参数是指请求传输连接的TSAP地址;
“被叫地址”参数是指与之建立传输连接的TSAP地址;
“响应地址”参数等于被叫地址参数;
“加速数据选择”参数是指在传输连接上是否可使用加速数据服务(如果声明没有这项服务,它就不能在传输连接上使用); “传输服务用户数据”参数是在传输用户之间传送的传输服务用户数据,传输服务提供者不进行修改,其长度为1~32字节; “服务质量”参数包括传输服务用户的一些要求,即QoS参数。
传输层要完成端到端的透明数据传输,至少要分为两个步骤:一是虚拟传输连接的建立(此处仍仅针对面向连接的传输层协议),二是源端用户数据沿着传输连接传送到目的端。
在整个数据传输过程中,传输层服务需要完成以下8个方面的基本功能:传输层寻址、传输连接建立、数据传输、传输连接释放、流量控制、拥塞控制、多路复用和解复用、崩溃恢复。
虽然网络层把数据分组从源主机传送到了目的主机,但是这并不代表数据的传输过程就全部完成了,因为数据分组还没有真正地交付给相应的应用进程,此时应用进程才是数据通信主体。而我们又知道,同一时间的通信双方可能存在许多并发应用进程,那么源端来的数据分组该交给哪个应用进程呢?这就涉及传输层的寻址问题了。
前面已介绍了TSAP(传输服务访问点),它代表的是一个传输层端口,因为传输层是以一个端对应一个应用进程来表示的。
在一台服务器上有大量潜在的服务进程,但是大多数服务进程又很少使用,那么让每个服务进程都主动、持续地监听一个TSAP地址显然是非常不明智的,也浪费了大量的服务器资源。
为了解决以上问题,提出了两种更好的方案
它先由进程服务器为各应用进程集中建立初始传输连接,然后再转给对应的服务进行正式的传输连接。进程服务器的TSAP地址分配方案的做法不是让每一个对外提供的服务都在一个特定的端口上监听,而是使用一个特殊的进程服务器(process server)来集中为那些较少使用的服务提供监听代理功能。它可以同时监听一组端口,以等待外来的连接请求。每个服务的潜在用户总是从一个Connect请求开始,在Connect请求中指定了这些用户想要的服务的TSAP地址。
例如,某公司有多个产品营销部门,每个部门设立了一个专门的售后服务热线电话。但其中有些部门的热线电话比较忙,经常有用户打电话咨询或投诉,而有些部门的热线电话打进来的人比较少。这时,如果仍为每个部门专门安排一个人负责热线电话,显然对于那些用户参与比较少的热线电话来说是一种浪费。这时我们肯定会想到,把这些用户参与比较少的部门的热线电话用一个总线电话来转接,只需要一个专门的接线员来管理总机即可。当有人打这个总线电话时,总机接线员询问所咨询的内容,然后再把电话转接到对应的部门分机,由对应的部门接线员进行处理,总机接线员又继续等待下一个用户电话
就像前面所说的那些用户参与比较多的部门热线电话,如果仍由总线来转接,总线接线员可能忙不过来,或者由于电话过多而使电话线路总处于占线状态而延误了处理时间。
这里还有一个问题,对于那些知名的服务,在用户主机应用进程中仍然非常多,但也并不是所有的应用进程总那么繁忙,如有的主机可能仅担当少数几种服务器角色,而绝大多数知名服务在这台主机中并没有实际上被提供。
因此,此时仍需要对这些知名服务提供集中的管理,以减少服务器资源的浪费。
名称服务器总是在监听一个特定的知名服务的端口(也就是我们通常所说的“常规端口”)。在这种方案中,为了找到与给定的服务名字相对应的TSAP地址(端口),用户需要与名称服务器建立一个连接,然后用户发送一条消息指定它想要的服务名字,名称服务器则发回相应的TSAP地址。随后,用户将它与名称服务器之间的连接释放,再与期望的服务建立一个新的连接。
名称服务器之所以知道这些知名服务的TSAP地址,是因为在一个新的服务被创建时必须向名称服务器注册,并把它的服务名字和TSAP地址告诉名称服务器。
在正常情况下,传输连接的建立过程比较简单,
所用到的传输服务原语是上文介绍的T_CONNECT.request、T_CONNECT.indication、T_CONNECT.response、T_CONNECT.confirm,
所用到的TPDU主要有CR TPDU和CC TPDU两个。
重复连接问题解决
如果网络非常拥塞,就会导致传输连接建立过程中所传输的确认TPDU分组都无法及时回到发送端,这样一来,传输连接发起方可能需要进行多次连接尝试。但问题远不是重试这么简单,因为这些延迟的分组可能在过一段时间后到达了,于是又会请求建立新的连接,这就出现了重复连接的问题。
三次握手机制:
所谓“三次握手”是指在建立连接时,发送端发送CR TPDU请求建立一个连接(第一次握手);接收端收到CR TPDU后发送一个CC TPDU进行应答(第二次握手),在应答分组中宣告了自己的初始连接序列号;发送端收到应答分组后发送第一个DT TPDU,对接收端初始序列号进行确认(第三次握手)。这样,一个连接才能建立起来,并且双方可以使用不同的起始序号。
当发生重复连接时,主机A就可以在第三次握手拒绝建立连接
一旦传输连接建立,传输协议即进入了正式的数据传输阶段。
ISO规定了正常数据传输和加速数据传输两种类型的服务,其中分别涉及了T_DATA.request、T_DATA.indication、T_EXPEDITED_DATA.request和T_EXPEDITED_DATA.indication四个传输服务原语,以及DT TPDU、AK TPDU,ED TPDU、EA TPDU四个TPDU。
传输连接的释放分为“对称释放”和“非对称释放”两种。
“对称释放”是在各自独立发出释放连接请求,收到对方的释放确认之后才可释放连接;
“非对称释放”是在发送释放请求后单方终止连接,但这样做有可能丢失对方发送的数据。
OSI/RM体系结构的传输连接释放也采用三次握手协商方式(TCP/IP体系结构中的TCP传输连接释放是采用“四次握手机制”的,具体内容将在后面介绍)
传输层协议采用的是在前面已多次提到的信用量(CDT)分配的窗口机制,不同于数据链路层协议流量控制方案中的窗口尺寸固定的滑动窗口机制,因为传输层中的CDT值是随着数据的传输过程而不断变化的(TCP/IP体系结构中的TCP的流量控制原理也是这样的,后面将具体介绍)。在传输层的CR、CC、AK三类TPDU头部中,均有一个CDT字段(相当于本章后面介绍的TCP数据段中的“窗口大小”字段),接收端利用该字段向发送端通报当前还可接收的TPDU数量,即接收缓冲区大小,发送端则按当前接收缓冲区容量发送适量的TPDU。
在建立连接时,双方通过CR TPDU和CC TPDU中的CDT字段捎带着相互通告各自的初始窗口大小,即初始信用量。在数据传输过程中,发送端按接收端发回的AK TPDU中的CDT值发送一定的数据量;接收端可根据接收缓冲区的使用状况动态地调整接收窗口大小,并在发送AK TPDU进行确认时捎带着将新的窗口大小通告给发送端。发送端将按新的接收窗口尺寸来调整发送窗口大小,接收端也用新的接收窗口大小来验证新到达数据分组的可接受性。
窗口大小为3的情况下的数据传输过程:
在传输层也可以采取多路复用(session multiplexing)技术来提高传输连接的利用率。传输层的多路复用可以是由多个传输连接复用同一个网络连接的向上多路复用方式,也可以是由一个传输连接在多个网络连接上循环传输的向下多路复用方式。
在传输连接中由于遇到主机或路由器不能正常工作而造成TPDU传输过程中断的现象称为崩溃。崩溃恢复就是要恢复到崩溃前的工作状态,继续TPDU传输。
总体来说,从第N层崩溃中恢复只能由第N+1层来完成,并且只能在第N+1层留有足够状态信息的情况下才能完成。
对于传输层崩溃恢复,需要先了解在崩溃前发送主机和接收主机的状态,以及发送主机对最后TPDU的处理。崩溃恢复工作必须由更高层次(应用层)来完成
具体在下文TCP可靠传输介绍
前面主要介绍了OSI/RM体系结构中的传输层服务,下面要具体介绍TCP/IP体系结构中的主要传输层协议—TCP(传输控制协议),其中包括TCP的一些主要特性和在本章前面介绍的各种传输服务功能实现的原理。
TCP是TCP/IP体系结构中最主要的传输层协议,在功能上与本章前面介绍的OSI网络中的TP4类传输层协议类似,但TCP只能提供面向连接的传输服务,而且TCP还具有以下主要特性:
(1)面向连接的传输协议
(2)仅支持单播传输
(3)提供可靠的交付服务
(4)传输单位为数据段
(5)仅一种TPDU格式
(6)支持全双工传输
(7)TCP连接是基于字节流的,而非报文流
(8)每次发送的TCP数据段大小和数据段数都是可变的
TCP的协议数据单元仍采用传统意义上的叫法,称为Segment(分段),而没有像OSI/RM中的那样称为TPDU,当然两者本质上其实是一致的。
TCP中只有一种TPDU格式,所有类型的数据段格式都统一
(1)URG
Urgent Pointer(紧急指针)控制位,指出当前数据段中是否有紧急数据,占1位,置1时表示有紧急数据。紧急数据会优先安排传送,而不会按照原来的排队顺序进行发送,相当于本章前面介绍OSI/RM传输层TPDU时所说的“加速数据”。仅当本字段的置1,后面的“紧急指针”字段才有意义。
(2)ACK
Acknowledgement(确认)控制位,指示TCP数据段中的“确认号”字段是否有效,占1位。仅当ACK位置1时才表示“确认号”字段有效,否则表示“确认号”字段无效,应用层实体在读取数据时可以不管“确认号”字段。
(3)PSH
Push(推)控制位,指示是否需要立即把收到的该数据段提交给应用进程,占1位。当PSH位置1时要求接收端尽快把该数据段提交给应用进程,而置0时没这个要求,可以先缓存起来。
(4)RST
Reset(重置)控制位,用于重置、释放一个已经混乱的传输连接,然后重建新的传输连接,占1位。当RST位置1时,释放当前传输连接,然后可以重新建立新的传输连接。
(5)SYN
Synchronization(同步)控制位,用来在传输连接建立时同步传输连接序号,占1位。当SYN位置1时,表示这是一个连接请求或连接确认报文。当SYN=1,而ACK=0时,表明这是一个连接请求数据段(相当于本章前面介绍的OSI/RM TPDU中的CR TPDU)。如果对方同意建立连接,则对方会返回一个SYN=1、ACK=1的确认(相当于本章前面介绍的OSI/RM TPDU中的CC TPDU)。
(6)FIN
Final(最后)控制位,用于释放一个传输连接,占1位。当FIN位置1时,表示数据已全部传输完成,发送端没有数据要传输了,要求释放当前连接,但是接收端仍然可以继续接收还没有接收完的数据。在正常传输时,该位置0。
在前面介绍OSI/RM的传输层服务时,提到过传输通信两端的端点就是TSAP地址,对应的就是传输层协议端口。在TCP/IP网络中,同样有端点的概念,但它并不是直接采用OSI/RM中的TSAP叫法,而是称为“套接字”(Socket),就像在TCP中仍然把所传输的数据称为“数据段”,而没有采用OSI/RM中的TPDU叫法一样。
当然,需要说明的是,Socket并不能直接等同于TSAP,它们只是类似,实际上Socket只是利用了TSAP地址,因为在它所包括的一组参数中就有TSAP地址—端口。
在TCP/IP网络中,区分不同应用程序进程间的网络通信和连接时主要有以下3个参数:通信的目的IP地址、使用的传输层协议(TCP或UDP)和使用的端口号(此处说明一下,Socket不仅在TCP中有,在UDP中也同样有)
通过将这3个参数结合起来,与一个Socket进行绑定,应用层就可以与传输层一起通过套接字接口区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。
为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP交互提供了称为套接字(Socket)的接口。
Socket可以看成是在两个网络应用程序进行通信连接时的一个端点(或者称为“逻辑接口”),它是连接应用程序和网络驱动程序的桥梁
在TCP/IP通信中,应用程序把数据传送给Socket,然后由Socket通过传输层向下提交给网络驱动程序并向网络上发送出去。计算机从网络上收到与该Socket绑定IP地址和端口号相关的数据后,由网络驱动程序通过传输层向上提交给应用层的Socket,最后应用程序从Socket中提取所要接收的数据。通信双方计算机上的网络应用程序就是这样通过Socket进行数据的发送与接收的
使用模型:
这里会涉及到一个问题,为什么客户端不需要调用BIND绑定网络地址?
因为一个主机上可能会有多个网卡及多个IP地址, 服务器调用BIND来绑定一个网络地址(IP地址),从而只监听这一个网络地址上的收到的的请求连接
而客户端上虽然有多个ip地址,但并没有要求一定要用哪个ip地址发送, 因此由系统内核来自动选择。因此不用绑定网络地址。
这里再深入介绍一下ACCEPT的工作原理:
accept主要用于服务器端,一般位于listen之后,默认会阻塞进程,直到有一个客户请求连接,建立好连接后,它返回的一个新的套接字 socketfd_new ,此后,服务器端即可使用这个新的套接字socketfd_new与该客户端进行通信,而sockfd 则继续用于监听其他客户端的连接请求。
那么,这个新的套接字 socketfd_new 与监听套接字sockfd 是什么关系?它所代表的socket对象包含了哪些信息?socketfd_new 是否占用了新的端口与客户端通信?
首先,一个端口肯定只能绑定一个socket。服务器端的端口在bind的时候已经绑定到了监听套接字socetfd所描述的对象上,accept函数新创建的socket对象其实并没有进行端口的占有,而是复制了socetfd的本地IP和端口号,并且记录了连接过来的客户端的IP和端口号。
那么,当客户端发送数据过来的时候,究竟是与哪一个socket对象通信呢?
客户端发送过来的数据可以分为2种,一种是连接请求,一种是已经建立好连接后的数据传输。
由于TCP/IP协议栈是维护着一个接收和发送缓冲区的。在接收到来自客户端的数据包后,服务器端的TCP/IP协议栈应该会做如下处理:如果收到的是请求连接的数据包,则传给监听着连接请求端口的socetfd套接字,进行accept处理;如果是已经建立过连接后的客户端数据包,则将数据放入接收缓冲区。这样,当服务器端需要读取指定客户端的数据时,则可以利用socketfd_new 套接字通过recv或者read函数到缓冲区里面去取指定的数据(因为socketfd_new代表的socket对象记录了客户端IP和端口,因此可以鉴别)。
传输层TSAP地址就是传输层协议端口,是对网络应用进程的一种标识。这里要区分“端口”与“接口”两个不同概念,接口是物理的,而“端口”却是一种抽象的软件结构,包括一些数据结构和I/O(输入/输出)缓冲区,故属于软件接口范畴,是传输层TSAP地址。
每个端口都拥有一个称为“端口号”的整数描述符,用来标识不同的端口或进程。在TCP数据段格式中,分别定义一个16比特长度的“源端口”和“目的端口”两个字段,也就是说,可定义2^16个端口,其端口号为0~2^16-1(65535)
可以将这65535个TCP端口分为以下三大类(它们是由IANA管理的)
通常将0~1023号TCP端口保留,因此,这类端口也称为“常规端口”,或者“公认端口”(well-known port)。这些端口基本上都已固定地分配给了已知的网络应用协议,如HTTP(对应WWW服务)中的80号端口、Telnet协议中的23号端口、SMTP中的25号端口等。
动态分配端口的端口号一般都大于1024,它们没有分配给固定的网络应用服务,因此,可以动态地分配给任意网络服务应用程序使用。也就是说,在使用网络应用软件访问网络时,网络应用软件可以向系统申请一个大于1024的端口临时代表这个软件与传输层交换数据,并且使用这个临时的端口与网络上的其他主机通信。
注册端口比较特殊,它也是固定为某个应用服务的端口,但是它所代表的不是已经形成标准的应用层协议,而是某个软件厂商开发的应用程序,如CCProxy中的8080号端口。
前面一直在说TCP是一个可以提供可靠数据传输的传输层协议,那么它到底是如何来保障可靠传输的呢?下面进行具体的分析。
在TCP可靠传输方面,主要采用以下4种机制:
一是“字节编号机制”
二是“数据段确认机制”
三是“超时重传机制”
四是“选择性确认(Selective ACK,SACK)机制”
(1)TCP可一次连续发送多个数据段
段)就可以一次性连续发送多个数据段,这样可大大提高数据发送效率。但一次性可发送多少个数据段是受对方返回的“窗口大小”字段值和当前可用“发送窗口”大小双重限制的。因为发送端对还没有收到确认的数据段要进行缓存,这需要占用一定的“发送窗口”大小。
(2)仅对连续接收的数据段进行确认
返回的确认数据段中的“确认号”字段值仅代表对端已正确接收的连续数据段(最高字节序号+1),而不一定是已正确接收数据段中的“最高序号+1”,因为中间可能还有些数据段因为网络延迟而暂时未收到,或出现了传输错误而丢失了。
(3)不连续序号的数据将先缓存
当主机接收到的数据段序号不连续时,不连续部分不会向应用层的应用进程进行提交,而是先缓存在“接收窗口”中,等待接收到中断的序号的数据段后再一起提交。
“超时重传”是TCP保证数据可靠性的另一个重要机制,其原理是在发送某一个数据段以后就开启一个超时重传计时器(Retransmission Timer,RTT)。如果在这个定时器时间内没有收到来自对方的某个数据段的确认,发送端启动重传机制,重新发送对应的数据段,直到发送成功为止。
要注意的是,并不是RTT定时器一到,就会立即重传数据,毕竟从“发送窗口”缓存中找到对应的数据段,然后安排重新发送都是需要时间的,实际上,超时重发的时间间隔(Retransmission Time Out)要大于RTT值。
这里涉及两个重要问题:一是如何确定RTT值,另一个是如何计算RTO值。表面上看起来RTT值容易确定,因为它就是一个数据段往返发送端和接收端的时间总和,但在TCP通信中,中间可能经过了多个性能不一样的网络,而且不同时刻网络的拥塞程度可能不一样,这就造成不同数据段的RTT时间并不一致,甚至波动非常大。但TCP必须适应这种情况,必须能动态地跟踪这些变化并相应地改变其超时重传时间。
正因为RTT值不是固定的,所以就出现了平滑RTT(SRTT)的概念,就是在充分考虑历史RTT值的情况下所设计的一个RTT值计算公式。
SRTT(新的SRTT)=αSRTT(旧的SRTT值)+(1-α)RTT(新的RTT样本值)
SRTT的初始值就是第一个RTT值。这里的α是一个平滑因子,它决定了旧的SRTT值所占的权重,0≤α<1。RFC2988推荐的α典型值为0.125。如果α很接近0,则表示新的SRTT值与旧的SRTT值很接近,变化不大,相反,则表示变化比较大
正常情况下,TCP使用β SRTT作为重传超时间隔(β>1),而且最初的值总为2(也就是在两倍SRTT时间后还没收到对应数据段的确认才重传该数据段)。
在1988年,Jacobson提出使用平均偏差作为标准偏差(就是β SRTT)的新估计算法,要求维护另一个被平滑的偏差RTTD。当一个确认数据段到达时,可以得出SRRT和新的RTT样本值之间的偏差RTTD=(SRTT-RTT)。第一次测量时,RTTD为测量到的RTT样本值的一半,在以后的测量中按照以下公式进行计算:
RTTD(新的RTTD)=αRTTD(旧的RTTD)+(1-α)×(SRTT-RTT)
并且将超时重传时间设置为:
RTO=SRTT+4×RTTD
在计算加权平均RTT时,只要数据段被重发了,就不采用其往返时间作为计算SRTT和RTO的样本,这样得出的加权平均SRTT值和RTO值比较准确。
在上面介绍的TCP重传机制中,如果在重传定时器超时后仍没收到一个数据段的确认,则可能会重传对应序号后面的所有数据段,因为后面的这些数据段均暂时不会被确认,这明显大大降低了TCP数据传输性能。
为了避免这种现象的出现,在RFC3517中出现了一种称为“选择性确认”(SACK)的机制,就是在TCP数据段格式的头部“可选项”字段中添加一个代表支持SACK的选项。但这个选项在不同的数据段中有不同的字段名称和不同的含义。
假设接收端已收到1、101、201、401、501这五个序号的数据段,在发送确认号为301的确认数据段时,在SACK扩展选项中标记401(起始序号为401,结束序号为500)和501(起始序号为501,结束序号为600)这两个不连续的数据段。这时发送端就会知道,不需要再发送401和501这两个数据段了,只需发送301号数据段即可。这样大大节省了网络资源,也提高了数据传输效率。
一般说来,我们总是希望数据传输得更快一些。但如果发送方把数据发送得过快,接收方就可能来不及接收,这就会造成数据的丢失。
流量控制(flow control)就是让发送方的发送速率不要太快,既要让接收方来得及接收,也不要使网络发生拥塞。
利用滑动窗口机制可以很方便地在 TCP 连接上实现流量控制。
持续计时器:
TCP 为每一个连接设有一个持续计时器。
只要 TCP 连接的一方收到对方的零窗口通知,就启动持续计时器。
若持续计时器设置的时间到期,就发送一个零窗口探测报文段(仅携带 1 字节的数据),而对方就在确认这个探测报文段时给出了现在的窗口值。
若窗口仍然是零,则收到这个报文段的一方就重新设置持续计时器。
若窗口不是零,则死锁的僵局就可以打破了。
基于传输效率的考虑:
在一些交互式应用中,每次传输的数据部分可能仅一个或几个字节,如果为每个这样的数据传输一次,显然传输效率是很低的,因为使用几十个协议头而最终传输的有用数据却仅几个字节。这类情况还会在发送确认数据段时经常发生,如果仅是用来确认的数据段,里面的数据量是非常小的,也正因如此,所以通常是在捎带大量数据的数据段中把ACK字段置1,同时起到确认的作用。
可以用不同的机制来控制 TCP 报文段的发送时机:
第一种机制是 TCP 维持一个变量,它等于最大报文段长度 MSS。只要缓存中存放的数据达到 MSS 字节时,就组装成一个 TCP 报文段发送出去。
第二种机制是由发送方的应用进程指明要求发送报文段,即 TCP 支持的推送(push)操作。
第三种机制是发送方的一个计时器期限到了,这时就把当前已有的缓存数据装入报文段(但长度不能超过 MSS)发送出去。
在某段时间,若对网络中某资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏——产生拥塞(congestion)。
出现资源拥塞的条件:
对资源需求的总和 > 可用资源
若网络中有许多资源同时产生拥塞,网络的性能就要明显变坏,整个网络的吞吐量将随输入负荷的增大而下降。
拥塞控制是一个全局性的过程,涉及到所有的主机、所有的路由器,以及与降低网络传输性能有关的所有因素。
发送方维持一个叫做拥塞窗口 cwnd (congestion window)的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口。如再考虑到接收方的接收能力,则发送窗口还可能小于拥塞窗口。
发送方控制拥塞窗口的原则是:只要网络没有出现拥塞,拥塞窗口就再增大一些,以便把更多的分组发送出去。但只要网络出现拥塞,拥塞窗口就减小一些,以减少注入到网络中的分组数。
慢开始算法的原理:
在主机刚刚开始发送报文段时可先设置拥塞窗口 cwnd = 1,即设置为一个最大报文段 MSS 的数值。
在每收到一个对新的报文段的确认后,将拥塞窗口加 1,即增加一个 MSS 的数值。
用这样的方法逐步增大发送端的拥塞窗口 cwnd,可以使分组注入到网络的速率更加合理
拥塞避免原理:
当拥塞窗口cwnd超过了慢开始门限,则每次收到确认后,只让拥塞窗口+1
设置慢开始门限状态变量:
慢开始门限 ssthresh 的用法如下:
当 cwnd < ssthresh 时,使用慢开始算法。
当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法。
当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞避免算法。
拥塞避免算法的思路是让拥塞窗口 cwnd 缓慢地增大,即每经过一个轮次就把发送方的拥塞窗口 cwnd 加 1,而不是加倍,使拥塞窗口 cwnd 按线性规律缓慢增长。
当网络出现拥塞时:
无论在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有按时收到确认),就要把慢开始门限 ssthresh 设置为出现拥塞时的发送方窗口值的一半(但不能小于2)。
然后把拥塞窗口 cwnd 重新设置为 1,执行慢开始算法。
这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。
在网络体系结构的“传输层”中,主要的传输层协议就是前面介绍的TCP,它是可靠的传输层协议,可以提供可靠的数据传输。然而,还有一些网络应用,应用的连续性和可靠性可能更重要,如视频会议、语音电话,其中丢失一部分数据的影响并不大,用户通过上、下部分的内容可能猜得出来,甚至这部分影响很难看得出来,但如果出现传输中断,或者延迟严重,可能就无法接受了。于是,出现了一种不面向连接的传输层—UDP(User Datagram Protocol,用户数据报文协议)。
UDP是一种无连接传输层协议,不像TCP那样需要服务器监听,也不必等待客户端与服务器建立连接后才能通信,当然,最后能否把数据传输成功,UDP是不能保证的。
UDP具有以下几个方面的明显特性:
(1)无连接性
在使用UDP进行数据传输前是不需要建立专门的传输连接的,当然,在数据发送结束时也无须释放连接了。
(2)不可靠性
因为UDP传输数据时是不需要事先建立专门的传输连接的,所以它的传输是不可靠的(但会尽最大努力进行交付)
(3)以报文为边界
UDP直接对应用层提交的报文进行封装、传输,但不拆分,也不合并,保留原来报文的边界。因此,UDP是报文流,而TCP是字节流。因为UDP不拆分报文,自然也就没有报文段之说,但UDP报文传输到网络层后,在网络层仍然可以根据网络的MTU值进行分割。
(4)无流量控制和拥塞控制功能
使用UDP进行数据传输时不能进行流量控制和拥塞控制,因为这类数据传输的连续性要比数据的完整性更重要,允许数据在传输过程中有部分丢失,如IP电话、流媒体通信等。
(5)支持各种交互通信方式
TCP不支持组播、广播通信方式,只支持一对一的单播方式,但UDP支持各种通信方式,即可以是一对一、一对多、多对一和多对多的方式。
计算机网络中有许多使用UDP的应用服务,如DNS、SNMP、DHCP和RIP等。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。