协议概述
进程之间的通信
- 我们通常感觉,信息传输的尽头是主机,但实际上,是主机中的进程
- 网络层的主要提供主机之间的逻辑通信
- 运输层提供的则是应用进程之间的端到端的逻辑通信
- 运输层向高层用户屏蔽了下面网络核心的细节
- 它使应用进程看见的就是好像在两个运输层实体之间有一条端到端的逻辑通信信道
- 面向连接的TCP还保证了可靠稳定的通信
- 复用:不同的应用进程都可以使用同一个运输层协议
- 分用:接收方的运输层在剥去报文的首部后能够把数据交付给正确的应用进程
- 某小区有一个收发室,小区内的所有栋都共用一个收发室,这就叫做复用
- 收发室能够将信件交付给对应的栋/个人,就叫做分用
传输控制协议TCP(Transmission Control Protocol)
用户数据报协议UDP(User Datagram Protocol)
运输层的端口
- 我们把进程作为通信的终点,其实也是不可行的,因为进程的创建和撤销都是动态的,通信的一方,几乎无法识别对方机器上的进程
- 解决的办法就是在运输层使用协议端口号
- 我们将报文传输到目的主机的某一个何时的目的端口,剩下的工作,就由TCP来完成
- 此处的端口,指的是软件端口,和路由器或交换机上的硬件端口是完全不同的概念
- TCP运输层应用一个16位的65535个端口号来标志一个端口,端口号只具有本地意义
运输层的端口号分为以下两大类
- 1.服务器端使用的端口号
- (1)熟知端口号:数值为0-1023,分给了TCP/IP协议中最重要的一些应用
- (2)登记端口号:数值为1024-49151
- 2.客户端使用的端口号
- 数值为49152-65535
- 这类端口号是留给客户进程选择暂时使用
- 当服务器进程收到客户进程的报文时,就知道了客户进程所使用的端口号
- 因为可以把数据发送给客户进程
- 通信结束后,刚才是用过的客户端口号就不复存在了
UDP
概述
- 只是在IP的数据报服务之上添加了很少的功能:复用和分用,以及差错检测
- 特点
- 无连接
- 不保证可靠交付
- 面向报文,即你给我多长的报文,我就一次发多长
- 没有拥塞控制
- 支持一对一,一对多,多对一,多对多的交互通信
- 首部开销小,只有8字节,比TCP的20字节的首部要短
UDP的首部格式
- 计算检验和的方式有些特殊
- 就是在前面添加一个伪首部
- 该伪首部即不上传,也不下传,只是用来计算检验和
TCP概述
特点
- 面向连接的运输层协议,只能是点对点的
- 提供可靠交付的服务,即保证无差错,不丢失,不重复,并且按序到达
- 全双工通信。两端都设有缓存。在进行发送时,应用程序只需要将数据发送至缓存,即可继续做自己的事。而在接收端,只需要将网络上的数据存入缓存,在合适的时机,由应用进程自己读取数据
- 面向字节流,可能进行拆分。不保证运输层收到的数据块,和发出去的数据块大小一致,但是目的地运输层收到的字节流肯定一致
TCP的连接
- 套接字
- TCP的两个端点就是套接字
- 套接字socket = {IP地址:端口号}。192.168.4.5:80
- TCP连接::={socket1, socket2} = {(IP1 : port1), (IP2 : port2)}
- 同一个IP地址尅有多个不同的TCP连接
- 同一个端口号也可以出现在多个不同的TCP连接中
TCP可靠传输的工作原理
超时重传/停止等待
-
在传输的过程中,出现了差错
-
当发送端未收到确认信息的时间,超过了设置的超时时间,则自动重发
-
注意
-
因此,发送时,必须保留已发送的副本
-
发送信息和确认信息都应编号,不然无法区分确认消息对应的是哪个数据
-
超时时间的设置应该比正常数据传输往返的时间长一些,防止只是信道延迟大,而不是出错
确认信息丢失/确认信息迟到
连续ARQ协议
- 就是维持一个窗口
- 在窗口内的分组都能够发送
- 每当收到一个分组的确认信息,则窗口就右滑
- 当然,接收方也可以累计接收信息,然后发送按序到达的最后一个分组的确认信息
- 这样有好处也有坏处
- 好处就是:如果其中某个分组的确认信息丢失了,那么我们也不需要进行重传
- 坏处就是:接收方不能向发送发反映已经正确接收到的分组的信息
TCP报文段的首部格式
报文段首部的前20字节是固定的,后面的4N字节,按需添加,因此,首部最小长度就是20字节
各字段的意义
- 源端口和目的端口:各占2字节
- 序号seq:占4字节。1-232中循环,即mod 232。传送的字节流中的,诶一个字节都按顺序编号。例如,一段白问的序号字段值是301,携带的数据有100字节。这就表明,本报文段的数据的第一个字节的序号是301,最后一个字节的序号是400,显然,下一个报文段的数据序号应当从401开始,即下一个报文段的序号字段值为401
- 确认号ack:占4字节。例如上例中,接收端收到的序号为301,长度为100的数据,则,为了保证连续,下次它希望收到的数据序号是401,则确认号就是401
- 数据偏移:占4位。指出TCP报文段的数据,距离TCP报文段起始处有多远。即,从报文段首部开始数,多少位之后,就是数据 注意,偏移单位是32位/4字节。因为4位最大为15,因此数据偏移最大值是60字节,这也是TCP首部得最大长度
- 保留:占6位,今后使用,默认0
- 紧急URG(urgent):当为1时,表示此报文段有紧急数据,应尽快传送,而不要按照原来的排队顺序来传送
- 确认ACK(ACKnowlegment):当其为1时,确认号字段才有效。TCP规定,在建立连接后,所有传送的报文段,都必须把ACK设置1
- 推送PSH:1时,就是立即创建一个报文段,并发出去,而不必等缓存填满再向上交付
- 复位:1时,表明TCP连接出现严重差错,必须释放连接,然后再重新建立连接当
- 同步SYN(SYNchronization):SYN为1时。当ACK=0表示这是一个连接请求,当ACK=1,表示这是一个连接确认请求。
- 终止FIN(FINis):=1时,表示报文段的发送方数据已发送完毕,要求释放连接
- 窗口:占2字节,传送数据窗口的大小
- 检验和:占2字节
- 紧急指针:占2字节,和URG一起使用,表示紧急数据的字节数
- 选项:长度可变,最长40字节。不使用选项时,TCP首部长度20字节。其中,有一个时间戳选项,是为了区分,在高速传输时,短时间内,232被用尽后从1再次开始,而出现的相同序号的报文段
可靠传输的实现
以字节为单位的窗口滑动
-
发送过的数据,在未收到确认之前偶读必须暂时保留,以便超时重传时使用
-
三个指针:
-
小于P1的是发送并且已经收到确认消息的
-
大于P1小于P2的,是已经发送,但是还未收到确认的
-
大于P2小于P3的,是允许发送,但是还未发送额
-
大于P3的,是窗口还未移到,不允许发送的
-
如果发送的消息,其实已经接收到了,但是返回的确认信息丢失了,那么我们只要没有收到确认信息。一律还是按照未收到认定
-
确认一个移一个
-
哪怕后面的数据都受到确认信息了,但是最开始的一个没收到
-
那么滑动窗口也不能移动,必须要等待最前面的确认消息才能滑动
-
强调三点
-
1 :
-
虽然A的发送窗口是根据B的接受窗口确定的,但是同一时刻两个窗口并不一定是一样大小的。因为网络中还有延迟存在。
-
并且,在拥塞情况下,A发送方,还会减小窗口的大小
-
2:
-
对于不是按序到达的数据(比如31还没收到,却先收到了32.33),如果都丢弃,将会造成网络资源的极大浪费
-
因此我们将其先放在缓存中,等收到缺少的部分后,再将其上传应用层
-
3:
-
TCP要求接收方必须有累积确认的功能,即累积几条确认消息再发送。
-
但是最长,只能延迟0.5s
超时重传(最后的改进没看懂)
TCP的流量控制
利用滑动窗口实现流量控制
- 流量控制:就是让发送方的发送速率不要太快,要让接收方来得及接收
必须考虑传输效率
- 如果我们发送1字节的信息,但是就会变成21字节的TCP报文段,41字节的IP报文段
- 这是十分低效的
- 可以进行延迟发送,当到达的数据已经达到发送窗口大小的一半或报文段的最大长度时,就立即发送
TCP的拥塞控制
拥塞控制的一般原理
- 拥塞:当对于网络中某一资源的需求,超过了该资源所能提供的可用部分
- 拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载
- 一些检测网络拥塞的指标:由于缺少缓存空间而被丢弃的分组的百分数;平均队列长度;超时重传的分组数;平均分组时延;分组时延的标准差等
几种拥塞控制方法
-
假定
-
数据是单向的,接收方只传送确认
-
接收方总是有足够大的缓存空间
-
慢开始
-
发送方维持一个叫做拥塞窗口的状态变量,其大小取决于网络的拥塞程度,动态变化
-
发送放让自己的发送窗口等于拥塞窗口
-
在初始时,我们不知道网络中的状况,不能立即把大量的数据注入到网络中
-
我们的方法总是先探测一下,即,由小到大逐渐增大拥塞窗口
-
如果网络状况良好,则,下一次是本次的二倍
-
直到窗口达到了慢开始的门限大小
-
拥塞避免
-
当窗口大小达到慢开始门限的大小后,就不再指数增加
-
改为一轮增加1
-
慢开始和拥塞避免
-
在窗口小于拥塞窗口时,执行慢开始
-
当窗口指数增加到大于等于慢开始门限的时候,将窗口设为门限大小,开始拥塞避免,每轮+1
-
当网络拥塞时,重新开始,执行慢开始,并且慢开始门限变为发生拥塞时窗口的一半
快重传
- M12收到,但是M3丢失
- 虽然接收到了M456,但是,根据可靠传输的原则,是不能确认M456的
- 此时,重复三次确认M2,发送方就会知道,M3需要重传
- 这样就尽早的执行了快重传
快恢复
- 在发生上述问题时,执行乘法减小算法,即将门限减半
- 但是,接下来不执行慢开始算法(慢开始算法,需要从1开始,指数增长门限)
- 而是以减半后的门限数值,直接执行拥塞控制算法,即每轮+1
随机早期检测RED(Random Early Detection)
- 假定一个路由器对某分组的处理时间太长,就会导致该分组重传
- 或者路由器的队列满了,那么路由器只能丢弃新来的分组,也会导致重传
- 并且所有新来的都被丢弃的话,就会导致大量的TCP数据被丢弃,很多网络都会出现重传
- 重传会导致TCP认为网络发生了拥塞,但是是并没有发生
- 大量的连接会进入到慢开始状态,这就成为全局同步
- 为了解决这一问题:如下
- 经验证明,使最大门限等于最小门限的两倍,是合适的
TCP的运输连接管理
TCP连接建立的过程要解决以下三个问题:
1.要使每一方都能够确知对方的存在
2.要允许双方协商一些参数(如最大窗口值,时间戳等)
3.能够对运输实体资源进行分配(如,缓存大小,连接表中的项目等)
主动发起连接建立的应用进程叫做客户端
被动等待连接建立的应用进程叫做服务器
建立连接————三次握手
- 第一次是客户端向服务器端请求连接
- SYN=1,ACK=0时,指的是这是一个连接请求。seq=x是序列号。
- SYN=1,ACK=1时,指的这是一个连接确认请求。seq=y是新的序列号,ack=x+1是确认号
- 最后一个,是对连接确认请求的确认信息。seq=x+1是序列号,ack=y+1确认号
- 其中的seq指的就是TCP报文的序号,ack指的就是确认号,即下次希望收到的信息的序号
为什么要三次握手?两次可以吗?四次呢?
- 两次不可以!三次及以上可以,但是没必要。
- 原因
- 如果两次握手,考虑如下情况
- 当A发送连接请求,但是请求的报文丢失而未收到确认
- 于是A再重传一次连接请求,B收到后,发送确认连接,然后AB建立了连接
- 数据传输完毕后,连接释放
- 假定出现一种情况,即A发送的第一个连接请求,在某一网络节点长时间滞留了,在某一时刻后,又到达了B
- B误以为这是A的一次新的连接,假如采用两次握手,B在收到消息后,发出确认,则,就建立了连接
- 由于A并没有发出建立连接的请求,因此就不会理睬B的确认
- 但是B却以为连接已经建立,并一直等待A的数据
- 这就会造成B的资源被白白浪费
- 或者考虑如下情况B向A发送了确认,但是确认消息丢失,那么B如何确认A有没有收到自己发给A的消息呢?该不该重发呢?
释放/断开连接————四次握手
- 前面在TCP的首部中讲过,FIN=1指的是连接断开的请求
- 因为ACK=1时,ack才有效
- 而第一次断开的报文段,并没有ack,所以,第一次断开中就不需要ACK=1
- 1.A:我数据都发送完了,我要断开了啊
- 2.B:恩,好的,我收到你要断开的消息了(此时,就处于半关闭状态了)
- 3.B:我的数据也发完了,我也要断开了啊
- 4.A:恩,我收到你要断开的信息了。(此时,四次握手完成了)
- 此时,A心里还在嘀咕,我发出去的确认消息,B会不会可能没收到呢
- 所以A要等待2MSL的时间。因为如果B没有收到A的确认信息,则B将会重发FIN+ACK报文段(即3的信息),A必能够在2MSL的时间内收到该信息,然后再次重传确认信息,随后再次倒计时等待。
- 2*MSL的时间也是为了使得,从A发出去的所有消息,能从网络中消失。防止出现已经失效的连接请求报文段
TCP的保活计时器
- 客户端已经主动与服务器建立了TCP连接,如果客户端突然崩溃,那怎么办?
- 服务器有一个保活计时器,每收到一次客户端的信息,就重置该计时器
- 通常计时器为两小时
- 若超过计时器时间,则服务器就发送一个探测信号,每75min发送一次
- 若一连十次之后,都无相应,则判定客户端故障,断开连接