续TCP/IP技术回顾(3)—网际层
主要根据课本《高级计算机网络》李向丽整理。
1.5 传输层
传输层协议提供应用进程间的端到端的逻辑通信。而网际层协议提供主机间的逻辑通信。即使在不可靠的网际层(主机之间的逻辑通信)传输下,传输层也能提供可靠的传输。(所谓的逻辑通信就是指:传输层之间看似是在水平方向传送数据,但是事实上这两个传输层之间并没有水平方向上的物理连接)。传输层协议能提供应用的多路复用/分用服务、可靠数据传送、带宽保证及延迟保证等。网际层提供的是“best effort”尽力而为的服务,网际层提供的无连接服务不可靠(丢包、重复),并且路由器可能崩溃,或者传输线路中断,所以传输层必须足够健壮来解决网际层不可靠,不稳定的问题,比如说传输层可检测到包丢失、损坏、乱序等差错情况,采取相应措施;或者当数据传输过程中网络连接中断,传输层可与远程传输实体建立一新的网络连接,在中断处继续数据的传输。
具体解释一下传输层的作用:
第一,多路复用和分用。复用:当传输层从应用程序接收报文后要封装在传输层的段中再交给网际层发送。分用:当传输层从网际层接收数据后,必须将数据正确递交给某个应用程序。也就是传输层能够区分不同进程的数据并且加以区分处理。
可靠数据传输,比如传输层的TCP协议,提供了面向连接的,可靠的,具有拥塞控制的协议,这是为了弥补网络层不足所建立的。
此外,传输层还有寻址的功能,定位应用程序在哪里。以及流量的控制,防止接收端速度太慢造成溢出和丢包的现象。
流量控制和拥塞控制的区别是:流量控制只是端端之间,只需要管理两个端之间的流量传输即可,也就是局部的。但是拥塞控制是全局的,是整个网络所做的事情,需要所有的路由器主机一起努力完成的事情。在传输层,既有流量控制也有拥塞控制。
传输协议要解决的问题取决于网络底层所能提供的服务质量。我们能看出来,传输层除了分用复用以外,好多功能都是针对性的弥补网络层的不足而产生的。两者对应来理解,会对于传输层和网络层有更深的理解。
面向连接和无连接服务的区别在于在通信双方通信之前,是否需要先建立连接。换句话说就是,通信双方之间的数据传输是否基于双方需要建立连接。那么,面向连接就是在双方通信之前,必须建立连接,在通信过程中,整个连接的过程一直被监控和管理,在通信结束之后,则释放这个连接。相反,无连接服务是。两个实体之间的通信不需要建立好连接,需要通信时,直接将信息发送到“网络”上,让该信息在网上尽力传输到目的方。
在TCP/IP协议簇中,在IP层中使用了这两种协议服务。其中TCP提供面向连接的可靠的传输服务,它不提供广播和组播机制,包括了确认-重传机制、流量控制、计时定时器、连接管理等等。这一方面使得TCP连接适用在可靠性高的传输场合,如HTTP何FTP、TELNET等 。但是,另一方面呢就是也因此增加了开销。例如数据报的报头增大。UDP协议是非连接的不可靠传输机制。它在Ip之上仅提供了多路复用和数据差错检查服务。
1.5.1 端口和套接字
端口是指应用层的各个应用进程的数据,通过这个“门”向下传递给传输层,反过来呢就是让传输层知道接受到的报文数据如何正确传递交付到对应的应用层上的进程上。端口号就是用来标识应用进程的数字标识。其端口号的长度为16Bit;也就是能够标识2^16个不同的端口号。另外端口号根据端口范围分为2类。
服务端使用的端口号:1、熟知端口号:0-1023范围。由IANA(互联网地址指派机构分配给TCP/IP最重要的一些应用进程,为固定格式)。2、登记端口号:1024-49151为没有熟知端口号的应用程序使用的,需要给IANA注册登记,防止重复。
常见的熟知端口号:
应用进程 | FTP | TELNET | SMTP | DNS | TFTP | HTTP | SNMP |
端口号 | 21 | 23 | 25 | 53 | 69 | 80 | 161 |
客户端使用的端口号:数值范围为49152-65535.也叫作短暂端口号。是在客户端进程运行成功后动态选择的。
另外需要注意 是端口号只具有本地意义,即端口号只是标志本地计算机应用层的各进程。在因特网中,不同的计算机的相同端口号是没有联系的。
套接字(socket)。我们知道在网络中通过Ip来唯一标识一个主机。而通过端口号来标识一台主机中的不同应用进程。所以在网络连接中就出现了Socket套接字来标识一个主机上的某进程。使用TCP或UDP的服务时,需要一对套接字:客户套接字和服务器套接字。
套接字(Socket) = (Host IP , port)
1.5.2 用户数据报协议
用户数据报协议(UDP)是一个无连接的、不可靠的传输层协议。UDP只是在IP数据报所提供的服务之上增加了端口功能和差错检测功能,有了端口号,传输层就能实现复用和分用功能,提供进程到进程间的通信 。
–复用:源主机的UDP实体从不同端口中收集字节流作为数据块,并封装进UDP报文,然后将UDP报文段传送给IP层。
–分用:在接收方,UDP实体从IP层接收到UDP报文后,根据UDP首部的端口号,将UDP报文中的数据交付给相应的应用程序。
UDP数据报格式
源/目的端口号: 2字节,表示源主机以及目的主机上运行的应用进程所使用的端口号。
总长度:2字节,以字节表示的UDP数据报总长度,其值在8~65 535字节之间。
校验和字段,2字节,校验整个UDP数据报。计算校验和时,12字节的伪首部。
1.5.3 传输控制协议
TCP是一个面向连接的协议,为应用进程提供可靠的数据传输服务。TCP报文段的传输,必须经历三个阶段:建立TCP连接;在TCP连接上发送数据和接收数据;拆除TCP连接。TCP为了提供可靠的数据传输服务,采用了很多复杂机制: 确认与超时重传、流量控制、拥塞控制等机制。
TCP报文段格式
① 源和目的端口号,各16位。定义发送和接收该报文段的应用进程端口号。
② 序号,32位。TCP段中数据部分的第一个字节的序号。
③ 确认号,32位。期望从对方接收的报文段的序号。
④ 首部长度,4位。 TCP段首部长度(4字节单位)。
⑤ 保留,6位。
⑥ 控制字段,6位。定义6种控制位或标志位。
URG: 标识紧急指针是否有效
ACK: 标识确认序号是否有效
PSH: 用来提示接收端应用程序立刻将数据从tcp缓冲区读走
RST: 要求重新建立连接. 我们把含有RST标识的报文称为复位报文段
SYN: 请求建立连接. 我们把含有SYN标识的报文称为同步报文段
FIN: 通知对端, 本端即将关闭. 我们把含有FIN标识的报文称为结束报文段
⑦ 窗口大小,16位。说明发送方最多能发送多少字节。
⑧ 校验和,16位。用于检测TCP段可能出现的差错,校验范围包括首部和数据部分。计算校验和需要构造12字节的TCP伪首部。
⑨ 紧急指针,16位。当URG=1时,有效。TCP序号值加上紧急指针值,可得出数据部分紧急数据的最后一个字节。
⑩ 选项,0~40字节。长度可变,必须是4字节的整数倍。扩展TCP的功能,例如:“窗口扩大因子”选项。“最大段长”(MSS)选项。
连接管理
在数据传输前, TCP双方必须建立TCP连接。TCP以全双工方式传送数据。TCP建立连接的过程主要解决下列三个问题:
–确定对方的存在;
–协商参数,例如:最大TCP报文段长度、最大窗口大小、服务质量等等;
–分配传输层资源(例如:缓冲区大小、连接表中的项目等等);
三次握手建立TCP连接的过程
第一次握手:
客户端想要连接,创建传输控制块TCB,状态变为主动打开。发送给服务器不包含数据内容的连接请求报文。该请求报文首部中同步位SYN=1,同时选择一个初始序列号seq=x(携带了x个字节)。然后客户端进入 SYN-SENT (同步已发送)状态,告诉服务器我想和你同步连接。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。
第二次握手:
TCP服务器收到连接请求报文,如果同意连接则发送确认报文。为了保证下次客户端发送报文时seq序列号是正确的,需要发送确认号ack=x+1,同时确认号ack要生效必须发送ACK=1,再加上同步位SYN=1,序列号seq=y(携带Y个字节),然后服务器也进 入SYN-RCVD (同步已收到) 状态,完成同步连接。这个报文也是SYN报文,也不能携带数据,但是同样要消耗一个序号。
第三次握手:
客户端收到确认后还要再向服务器发送确认报文。确认报文已经不是请求报文SYN了,不再包含SYN同步位。发送的内容有序列号seq=x+1(和第二次握手的ACK对应),确认号ack=y+1,ACK=1。客户端发送确认报文以后进入ESTABLISHED(已建立)状态,服务器接收到确认报文以后也进入ESTABLISHED状态。此时TCP连接完成建立。
为什么非要三次握手呢?
主要是为了防止已经失效的连接请求报文突然又传到了服务器,从而产生错误。
如果是两次握手,假设一种情景:客户端发送了第一个请求连接报文并未丢失,只是因为网络问题在网络节点中滞留太久了。由于客户端迟迟没有收到确认报文,以为服务器没有收到。于是再发送一条请求连接报文,此时一路畅通完成两次握手建立连接,传输数据,关闭连接。然后那个前一条龟速的请求报文终于走到了服务器,再次和服务器建立连接,这就造成了不必要的资源浪费。
如果是三次握手,就算那一条龟速的请求报文最后到达了服务器,然后服务器也发送了确认连接报文,但是此时客户端已经不会再发出确认报文了,服务器也接受不到确认报文,于是无法建立连接。
释放TCP连接的过程
TCP连接的释放(四次挥手)
数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。
第一次挥手:
客户端从ESTABLISHED状态变为主动关闭状态,客户端发送请求释放连接报文给服务器,FIN=1,seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
第二次挥手:
服务器接收到客户端发来的请求释放报文以后,发送确认报文告诉客户端我收到了你的请求,内容差不多就是seq=v,ack=u+1,ACK=1,此时服务器进入CLOSE-WAIT(关闭等待)状态。
为什么是CLOSE-WAIT状态?可能自己服务器这端还有数据没有发送完,所以这个时候整个TCP的连接就变成了半关闭状态。服务器还能发送数据,客户端也能接收数据,但客户端不能再发送数据了,只能发送确认报文。
客户端接收到服务器传来的确认报文以后,进入 FIN-WAIT-1(终止等待2)状态,等待服务器发送连接释放的报文(在这之前,还需要接受服务器没有发送完的最后的数据)。
第三次挥手:
服务器所有的数据都发送完了,认为可以关闭连接了,于是向客户端发送连接释放报文,内容FIN=1,seq=w,ack=u+1(客户端没发送消息,所以提醒客户端下一次还是从u+1开始发送序列),ACK=1。此时服务器进入了 LAST-ACK(最后确认)状态,等待客户端发送确认报文。
第四次挥手:
客户端接收到了服务器发送的连接释放报文,必须发出确认。确认报文seq=u+1,ack=w+1,ACK=1。此时客户端进入 TIME-WAIT (时间等待)状态,但是没有立马关闭。此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
因为这个确认报文可能丢失。服务器收不到确认报文心想这可能是我没传到或者丢失了啊,于是服务器再传一个FIN,然后客户端再重新发送一个确认报文。然后刷新2∗∗MSL时间。直到这个时间内收不到FIN连接释放报文,客户端撤销TCB进入CLOSE状态。而服务器,在接收到确认报文的时候就立马变为CLOSE状态了。所以服务器结束TCP连接的时间略早于客户端。
万一确认连接以后客户端故障怎么办?
TCP设有一个保活计时器。显然客户端故障时服务器不会智障般等下去,白白浪费资源。服务器每次收到一次客户端的请求以后都会刷新这个保活计时器,时间通常设置为2小时。若2个小时依旧没有收到客户端的任何数据,服务器会发送一个探测报文段,每隔75分钟发一个,如果连发十个都没有数据反应,那么服务器就知道客户端故障了,关闭连接。
TCP的流量控制与拥塞控制
TCP连接的双方都为连接设置了接收缓存。相关的应用进程可以从该缓存中读取数据。TCP采用动态滑动窗口机制进行流量控制,防止由于发送方发送数据太快而造成接收方缓冲区溢出。
–发送方保存一个接收窗口的变量用于流量控制。接收窗口说明接收方还有多少可用缓存空间,发送方发送的数据量一定要小于接收窗口的大小。
当网络上有太多的数据报,超过了网络的容量,或者是网络资源使用、分配不合理时,就会出现数据报时延增加、丢弃概率增大、系统性能下降等到现象,这种现象被称为拥塞。产生拥塞的根本原因在于用户(主机)给网络提供的负载大于网络资源的容量和处理能力。显然,需要对拥塞现象进行控制。
TCP拥塞控制方法是让发送方感知拥塞,来限制其向TCP连接发送数据的速率。
–若发送方感知到从它到目的地之间的路径上没有什么拥塞,则增加发送速率;
–若发送方感知到有拥塞,则降低发送速率。
TCP连接的每一方都有拥塞窗口CongWin变量。要求发送方已经发送的但是未被确认的数据量,不要超过拥塞窗口和接收窗口的最小值。TCP发送方如果发现了“丢包”事件,即出现了超时(timeout),或者收到来自接收方的三个冗余ACK,则认为出现了拥塞。TCP拥塞控制算法(TCP congestion control algorithm):慢启动(slow start)、拥塞避免、快速重传和快速恢复等算法。