数据通信与网络技术
上QQ阅读APP看书,第一时间看更新

2.3 传输层协议

传输层主要为两台主机上的应用程序提供端到端的通信。在TCP/IPv4协议栈中,传输层包含传输控制协议(Transmission Control Protocol,TCP)和用户数据报协议(User Datagram Protocol,UDP)两个协议。

2.3.1 TCP和UDP的应用场景

传输层的TCP和UDP有各自的应用场景。下面分别介绍二者的应用场景。

1.TCP的应用场景

TCP为应用层协议提供可靠传输服务,发送端按顺序发送数据,接收端按顺序接收数据,若发生丢包、乱序等情况,TCP负责重传和排序。下面是TCP的应用场景。

(1)客户端程序和服务端程序需要多次交互才能实现应用程序的功能,比如接收电子邮件使用的POP3和发送电子邮件使用的SMTP,以及传输文件使用的FTP,在传输层使用的都是TCP。

(2)应用程序传输的文件需要分段传输,比如通过浏览器访问网页或者用QQ传输文件时,在传输层均会选用TCP进行分段传输。

例如,从网络中下载一个大小为500MB的电影或大小为200MB的软件,这么大的文件需要拆分成多个数据包进行发送,发送过程可能需要持续几分钟或几十分钟。在此期间,发送方以字节流的形式将发送的内容一边发送一边放入缓存,传输层会将缓存中的字节流分段并进行编号,然后按顺序发送。这一过程需要发送方和接收方建立连接,并协商通信过程的一些参数(比如一个分段最大多少个字节等)。需要说明的是,这里所说的段在网络层加上IP首部即可形成数据包。如果网络不稳定而造成某个数据包丢失,则发送方必须重新发送丢失的数据包,否则会造成接收的文件不完整,TCP协议能够实现可靠传输。如果发送方发送速度太快,接收方来不及处理,接收方还会通知发送方降低发送速度甚至停止发送,这就是TCP的流量控制功能。互联网中的流量不固定,流量高峰时有可能造成网络拥塞(这一点很好理解,就像城市里上下班高峰时的交通堵塞一样),来不及转发的数据包就会被路由器丢弃。TCP协议在传输过程中会一直探测网络是否拥塞,进而调整发送速度。TCP协议有拥塞避免机制。

如图2-23所示,发送方的发送速度由网络是否拥塞和接收端的接收速度两个因素控制,哪个速度低,就用哪个速度发送。

图2-23 TCP的功能

有些应用程序通信,使用TCP协议就显得效率低了。比如有些应用,客户端只需向服务器发送一个请求报文,服务器返回一个响应报文就完成其功能。这类应用如果使用TCP,发送3个数据包建立连接,再发送4个数据包释放连接,效率不高。这类应用,在传输层通常使用UDP。

2.UDP的应用场景

(1)客户端程序和服务端程序通信,应用程序发送的数据包不需要分段。比如域名解析,DNS协议在传输层就使用UDP,客户端向DNS服务器发送一个报文请求解析某个网站的域名,DNS服务器将解析的结果使用一个报文返回给客户端。

(2)实时通信。比如使用QQ、微信进行语音聊天、视频聊天。这类应用,发送端和接收端需要实时交互,也就是不允许较长延迟,即便有几句话因为网络堵塞没听清,也不需要使用TCP等待丢失的报文,因为如果等待的时间太长,就不能实现实时聊天了。

(3)组播或广播通信。比如学校的多媒体机房,教师的计算机屏幕上的内容需要教室的学生用计算机接收,在教师的计算机上安装多媒体教室服务端软件,在学生的计算机上安装多媒体教室客户端软件,教师计算机使用组播地址或广播地址发送报文,所有学生计算机都能收到。这类一对多通信在传输层使用UDP。

知道了传输层两个协议的特点和应用场景,就很容易判断某个应用层协议在传输层使用什么协议。接下来分析判断QQ传输文件在传输层使用什么协议以及QQ聊天在传输层使用什么协议。

使用QQ给好友传输文件,传输文件的过程会持续几分钟或几十分钟,肯定不是使用一个数据包就能把文件传输完的,这就需要将要传输的文件分段传输。在传输过程中需要实现的可靠传输、流量控制、拥塞避免等功能,均须在传输层使用TCP协议来实现。

使用QQ与好友聊天,通常一次输入的聊天内容不会有太多文字,使用一个数据包就能把聊天内容发送出去,并且聊完第一句,也不确定什么时候会聊第二句,即发送数据不是持续的,也就没必要让通信的两台计算机一直保持连接,因此,发送QQ聊天内容在传输层使用UDP。

综上可知,应用程序在传输层可以根据通信的特点选择不同的协议。

2.3.2 传输层协议和应用层协议之间的关系

应用层协议有很多,但是传输层就只有两个。那么如何使用传输层的这两个协议来标识不同的应用层协议呢?

通常用传输层协议加一个端口号来标识一个应用层协议。在传输层使用16位二进制标识一个端口,端口号取值范围是0~65535,这个取值范围对一台计算机来说足够用了。

端口号可分为两大类,即服务器使用的端口号和客户端使用的端口号。

(1)服务器使用的端口号。

服务器使用的端口号可分为两类,最重要的一类叫作熟知端口号(Well-Knownportnumber)或系统端口号,数值为0~1023。互联网数字分配机构(The Internet Assigned Numbers Authority,IANA)把这些端口号指派给了TCP/IP最重要的一些应用程序,让所有的用户都知道。下面给出一些常用的熟知端口号,如图2-24所示。

图2-24 熟知端口号

另一类叫作登记端口号,数值为1024~49151。这类端口号是给没有熟知端口号的应用程序使用的。使用这类端口号必须在IANA按照规定的手续进行登记,以防止重复。比如微软的远程桌面协议(Remote Display Protocol,RDP)使用TCP的3389端口,就属于登记端口号的范围。

(2)客户端使用的端口号。

当打开浏览器访问网站或登录QQ等客户端软件和服务器建立连接时,计算机会为客户端软件分配临时端口,这就是客户端端口,取值范围为49152~65535,由于这类端口号仅在客户进程运行时才被动态选择,因此又叫作临时(短暂)端口号。这类端口号是留给客户进程选择暂时使用的。当服务器进程收到客户进程的报文时,就知道了客户进程所使用的端口号,因而可以把数据发送给客户进程。通信结束后,刚才已使用过的客户端口号就不复存在了。这个端口号就可以供其他客户进程以后使用。

下面列出了一些常见的应用层协议默认使用的协议和端口号。

■HTTP默认使用TCP的80端口。

■FTP默认使用TCP的21端口。

■SMTP默认使用TCP的25端口。

■POP3默认使用TCP的110端口。

■HTTPS默认使用TCP的443端口。

■DNS默认使用UDP的53端口。

■RDP默认使用TCP的3389端口。

■Telnet默认使用TCP的23端口。

■Windows访问共享资源默认使用TCP的445端口。

■微软的SQL数据库默认使用TCP的1433端口。

■MySQL数据库默认使用TCP的3306端口。

以上列出的都是默认端口,也可以更改应用层协议所使用的端口。如果不使用默认端口,客户端需要指明所使用的端口。如图2-25所示,服务器运行了Web服务、SMTP服务和POP3服务,这3个服务分别使用HTTP、SMTP和POP3与客户端通信。现在网络中的A计算机、B计算机和C计算机分别打算访问服务器的Web服务、SMTP服务和POP3服务,并发送了3个数据包①②③,这3个数据包的目标端口分别是80、25和110,服务器收到这3个数据包后,就会根据目标端口将数据包提交给不同的服务。

总结:数据包的目标IP地址用于在网络中定位某一个服务器,目标端口用于定位服务器上的某个服务。

图2-25 端口和服务的关系

2.3.3 TCP首部

下面讲解TCP报文的首部格式。TCP协议能够实现数据分段传输、可靠传输、流量控制、网络拥塞避免等功能,因此,TCP报文首部相比UDP报文首部字段要多,并且首部长度不固定。如图2-26所示,TCP报文段首部的前20字节是固定的,后面有4N字节是根据需要而增加的选项(N是整数)。因此,TCP首部的最小长度是20字节。

图2-26 TCP首部

TCP首部固定部分各字段的含义介绍如下。

(1)源端口和目的端口各占2字节,分别写入源端口号和目的端口号,传输层端口号用来标识一个应用层协议。

(2)序号占4字节。序号范围是[0,232-1],共232(即4294967296)个序号。序号增加到232-1后,下一个序号就又回到0。TCP是面向字节流的。在一个TCP连接中传送的字节流的每一个字节都按顺序编号。整个要传送的字节流的起始序号必须在连接建立时设置。首部中的序号字段值指的是本报文段所发送的数据的第一个字节的序号。如图2-27所示,以A计算机给B计算机发送一个文件为例来说明序号和确认号的用法,为了方便说明问题,传输层其他字段没有展现,第1个报文段的序号字段值是1,而携带的数据共有100字节。这就表明:本报文段的数据的第1字节的序号是1,最后一字节的序号是100。下一个报文段的数据序号应当从101开始,即下一个报文段的序号字段值应为101。这个字段的名称也叫作“报文段序号”。

B计算机将收到的数据包放到缓存,根据序号对收到的数据包中的字节进行排序,B计算机的程序会从缓存中读取编号连续的字节。

(3)确认号占4个字节,是期望收到对方下一个报文段的第一个数据字节的序号。

TCP协议能够实现可靠传输,接收方收到几个数据包后,就会给发送方一个确认数据包,告诉发送方下一个数据包该发第几字节。如图2-27所示,B计算机收到两个数据包后,将两个数据包中的字节进行排序得到连续的前200字节,B计算机要发一个确认包给A计算机,告诉A计算机应该发送第201字节,这个确认数据包的确认号就是201。确认数据包没有数据部分,只有TCP首部。

总之,应当记住:若确认号是N,则表明到序号N-1为止的所有数据都已正确收到。

由于序号字段有32位长,可对4GB(即4千兆字节)的数据进行编号,在一般情况下可保证当序号重复使用时,旧序号的数据早已通过网络到达终点了。

图2-27 理解序号和确认号

(4)数据偏移占4位,它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。这个字段实际上指出了TCP报文段的首部长度。由于首部中还有长度不确定的选项字段,因此数据偏移字段是必要的。但请注意,“数据偏移”的单位为4个字节,由于4位二进制数能够表示的最大十进制数是15,因此数据偏移的最大值是60字节,这也是TCP首部的最大长度,也就意味着选项长度不能超过40字节。如果只有固定长度的20字节的首部,数据偏移值就是5,写成4位二进制数就是0101。

(5)保留占6位,保留为今后使用,但目前应置为0。

(6)紧急URG(URGent)。当URG=1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据),而不要按原来的排队顺序传送。例如,已经发送了一个很长的程序要在远程的主机上运行,但后来发现了一些问题,需要取消该程序的运行,因此,用户通过键盘发出中断命令(Control+C)。如果不使用紧急数据,那么这两个字符将存储在接收TCP的缓存末尾。只有在所有的数据被处理完毕后这两个字符才被交付给接收方的应用进程。这样做就浪费了许多时间。

当URG置为1时,发送应用进程就告诉发送方的TCP有紧急数据要传送。于是发送方TCP把紧急数据插入本报文段数据的最前面,而在紧急数据后面的数据仍是普通数据。这时要与首部中紧急指针(Urgent Pointer)字段配合使用。

(7)确认ACK(ACKnowlegment)。仅当ACK=1时确认号字段才有效。当ACK=0时,确认号无效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置为1。

(8)推送PSH(PuSH)。当两个应用进程进行交互式通信时,有时一端的应用进程希望在输入一个命令后立即就能收到对方的响应。在这种情况下,TCP就可以使用推送(Push)操作。即发送方TCP把PSH置为1,并立即创建一个报文段发送出去。接收方TCP收到PSH=1的报文段,就尽快地(即“推送”向前)交付给接收应用进程,而不再等到整个缓存都填满了后再向上交付。虽然应用程序可以选择推送操作,但推送操作很少使用。

(9)复位RST(ReSeT)。当RST=1时,表明TCP连接中出现严重差错(如主机崩溃或其他原因),必须释放连接,然后再重新建立传输连接。将RST置为1还可用来拒绝一个非法的报文段或拒绝打开一个连接。RST也可称为重建位或重置位。

(10)同步SYN(SYNchronization)。TCP在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使SYN=1和ACK=1。因此,SYN置为1就表示这是一个连接请求或连接接受报文。关于连接的建立和释放,在后面TCP连接管理部分将详细讲解。

(11)终止FIN(FINish,意思是“完”“终”)。TCP用来释放一个连接。当FIN=1时,表明此报文段的发送方的数据已发送完毕,并要求释放传输连接。

(12)窗口占2字节。窗口值是[0,216-1]之间的整数。TCP协议有流量控制功能,窗口值用来告诉对方:从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量(单位是字节)。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。总之,窗口值是接收方让发送方设置其发送窗口的依据。使用TCP协议传输数据的计算机会根据自己的接收能力随时调整窗口值,对方参照这个值及时调整发送窗口,从而达到流量控制功能。

(13)检验和占2字节。检验和字段检验的范围包括首部和数据这两部分。

(14)紧急指针占2字节。紧急指针仅在URG=1时才有意义,它指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据)。因此,紧急指针指出了紧急数据的末尾在报文段中的位置。在所有紧急数据都处理完后,TCP就告诉应用程序恢复正常操作。值得注意的是,即使窗口为零时也可发送紧急数据。

(15)选项长度可变,最长可达40字节。当没有使用选项时,TCP的首部长度是20字节。TCP最初只规定了一种选项,即最大报文段长度(Maximum Segment Size,MSS)。MSS是每一个TCP报文段中的数据字段的最大长度。数据字段加上TCP首部才等于整个TCP报文段,所以MSS并不是整个TCP报文段的最大长度,而是“TCP报文段长度减去TCP首部长度”。

2.3.4 TCP连接管理

TCP协议是可靠传输协议,使用TCP通信的计算机在正式通信之前需要先确保对方存在,并确定协商通信的参数,比如接收端的接收窗口大小、支持的最大报文段长度、是否允许选择确认( Selective Acknowledgement,SACK)、是否支持时间戳等。建立连接后就可以进行双向通信了,通信结束后,须释放连接。

TCP连接的建立采用客户端/服务器方式。主动发起建立连接的应用进程叫作客户端(Client),而被动等待建立连接的应用进程叫作服务器(Server)。下面将详细介绍TCP连接的建立与释放。

1.TCP连接的建立

建立TCP连接的过程如图2-28所示,客户端向服务端发起通信,客户端的TCP模块与服务端的TCP模块之间将通过“3次握手”(Three-Way Handshaking)来建立TCP会话。所谓“3次握手”,是指在TCP会话的建立过程中总共交换3个TCP数据包(没有数据,只有TCP首部),这3个数据包就是TCP协议建立连接的数据包。需要说明的是,不同阶段在客户端和服务端能够看到不同的状态。

服务端启动服务,就会使用TCP的某个端口侦听客户端的请求,等待客户的连接,状态也会由CLOSED变为LISTEN。下面具体介绍3次握手的过程,介绍中的英文缩写是区分大小写的,比如大写ACK表示ACK标记位,小写ack表示确认号的值。

(1)客户端的应用程序发送TCP连接请求报文,把自己的状态告诉对方,这个报文的TCP首部SYN标记位是1,ACK标记位为0,序号(seq)为x,这个x被称为客户端的初始序列号,这个值通常为0。发送出连接请求报文后,客户端就处于SYN_SENT状态。

图2-28 通过3次握手建立TCP连接

(2)服务端收到客户端的TCP连接请求后,发送确认连接报文,将自己的状态告诉客户端,这个报文的TCP首部SYN标记位是1,ACK标记位为1,确认号(ack)为x+1,序号(seq)为yy为服务端的初始序列号)。服务端就处于SYN_RCVD状态。

(3)客户端收到连接请求确认报文后,状态就变为ESTABLISHED,再次发送给服务端一个确认报文,用于确认会话的建立。该报文SYN标记位为0,ACK标记位为1,确认号(ack)为y+1。服务端收到确认报文,状态变为ESTABLISHED。

需要特别注意的是,经过3次握手之后,客户端和服务端之间其实建立起了两个TCP会话,一个是从客户端指向服务端的TCP会话,另一个是从服务端指向客户端的TCP会话。因为客户端是发起通信的一方,说明客户端有信息要传递给服务端,于是客户端首先发送了一个SYN段,请求建立一个从客户端指向服务端的TCP会话,这个会话的目的是控制信息能够正确而可靠地从客户端传递给服务端。服务端在收到SYN段后,会发送一个SYN+ACK段作为回应。SYN+ACK段的含义:服务端一方面同意了客户端的请求,另一方面也请求建立一个从服务端指向客户端的TCP会话,这个会话的目的是控制信息能够正确而可靠地从服务端传递给客户端。客户端收到SYN+ACK段后,会回应一个ACK段,表示同意服务端的请求。之后就可以进行双向可靠通信了。

2.TCP连接的释放

TCP通信结束后,需要释放连接。TCP连接释放过程比较复杂,我们仍结合双方状态的改变来阐明连接释放的过程。数据传输结束后,通信的双方都可释放连接。如图2-29所示,现在A和B都处于ESTABLISHED状态,A的应用进程先向其TCP发出连接释放报文段,停止发送数据,并主动关闭TCP连接。A把连接释放报文段首部的FIN置为1,其序号seq=u,它等于前面已传送过的数据的最后一个字节的序号加1。这时A进入FIN-WAIT-1(终止等待1)状态,等待B的确认。请注意,TCP规定:FIN报文段即使不携带数据,也会消耗掉一个序号。

B收到连接释放报文段后即发出确认,确认号是ack=u+1,而这个报文段自己的序号是v,等于B前面已传送过的数据的最后一个字节的序号加1。然后B就进入CLOSE-WAIT(关闭等待)状态。TCP服务器进程此时应通知高层应用进程,因而从A到B这个方向的连接就释放了,这时的TCP连接处于半关闭(Half-Close)状态,即A已经没有数据要发送了,但若B发送数据,A仍要接收。也就是说,从B到A这个方向的连接并未关闭。这个状态可能会持续一些时间。

图2-29 TCP连接释放的过程

A收到来自B的确认后,A就进入FIN-WAIT-2(终止等待2)状态,等待B发出连接释放报文段。若B没有要向A发送的数据,其应用进程就通知TCP释放连接。这时B发出的连接释放报文段必须使FIN=1。现假定B的序号为w(在半关闭状态B可能又发送了一些数据)。B还必须重复上次已发送过的确认号ack=u+1。这时B就进入LAST-ACK(最后确认)状态,等待A的确认。

A在收到B的连接释放报文段后,必须对此发出确认。在确认报文段中把ACK置为1,确认号ack=w+1,而自己的序号是seq=u+1(根据TCP标准,前面发送过的FIN报文段要消耗一个序号)。然后进入TIME-WAIT(时间等待)状态。请注意,现在TCP连接还没有释放掉。必须经过时间等待计时器(TIME-WAIT Timer)设置的时间2MSL后,A才进入CLOSED状态。时间MSL叫作最长报文段寿命(Maximum Segment Lifetime),RFC793建议设为2min。但这完全是从工程上来考虑的,对于现在的网络,MSL=2min可能太长了。因此,TCP允许不同的实现根据具体情况使用更小的MSL值。因此,从A进入TIME-WAIT状态后,要经过4min才能进入CLOSED状态,才能开始建立下一个新的连接。

2.3.5 TCP可靠传输的实现

TCP协议实现可靠传输使用的是滑动窗口协议和连续自动重传请求(Automatic Repeat-reQuest,ARQ)协议。下面具体介绍滑动窗口协议和连续ARQ协议的工作过程。

1.滑动窗口协议的工作过程

TCP协议建立连接后,双方可以使用建立的连接相互发送数据。为了讨论问题方便,这里仅考虑A发送数据而B接收数据并发送确认。因此,A叫作发送方,而B叫作接收方。

滑动窗口是面向字节流的,为了方便读者记住每个分组的序号,这里假设每一个分组是100字节。为了方便画图,将分组进行编号简化表示,如图2-30所示。不过务必要记住每一个分组的序号。

如图2-31所示,在建立TCP连接时,B计算机告诉A计算机它的接收窗口为400字节,A计算机就设置一个400的发送窗口。如果一个分组有100字节,在发送窗口中就有M1、M2、M3、M4共4个分组,发送端A就可以连续发送这4个分组,每一个分组都记录一个发送时间,如图2-31中t1时刻所示,发送完毕后,就停止发送。接收端B收到这4个连续分组,只需要给A发送一个确认,确认号为401,告诉A计算机400以前的字节已经全部收到。如图2-31中t2时刻所示,发送端A收到M4分组的确认,发送窗口就向前滑动,M5、M6、M7、M8分组就进入发送窗口,这4个分组就可以连续发送,发送完后,停止发送,并等待确认。这就是滑动窗口协议。

图2-30 简化分组表示

2.连续ARQ协议的工作过程

如果M7在传输过程中丢失,B计算机收到M5、M6和M8分组,B计算机收到连续的M1至M6分组,就会给A计算机发送一个确认,该确认的序号为601,告诉A计算机600之前的字节全部收到,图2-31中t3时刻,A计算机收到确认,并不是立即发送M7,而是向前滑动发送窗口,M9和M10进入发送窗口,发送M9和M10,什么时候发送M7呢?M7超时后就会自动重发,这个超时时间是比一个往返时间长一点的时间。如果发送了M9,M7就超时了,发送顺序就变成了M9、M7和M10。这就是连续ARQ协议。

图2-31 连续ARQ协议和滑动窗口协议

2.3.6 UDP

UDP与TCP一样用于处理数据包,在OSI模型中,二者都位于传输层(处于IP协议的上一层)。传输层的UDP是一个无连接的传输协议。UDP为应用程序提供了一种无须建立连接就可以发送IP数据包的方法。

UDP没有对发送的数据包进行排序、丢包重传、流量控制等功能。也就是说,在报文发送之后,无法得知其是否已安全完整地到达。UDP存在的意义更多的是利用UDP+端口来标识一个应用层协议。