应用进程之间的通信:
TCP/IP 的运输层有两个不同的协议:
在TCP/IP体系中,根据所使用的协议是TCP或UDP,分别称之为TCP报文段或UDP用户数据报
运行在计算机中的进程是用进程标识符来标志的,为了使运行不同操作系统的计算机的应用进程能够互相通信,就必须用统一的方法对 TCP/IP 体系的应用进程进行标志,解决的方法就是使用协议端口号,简称端口。
TCP/IP 的运输层是用一个 16 位端口号进行标志。端口号只具有本地意义,即端口号只是为了标志本计算机应用层中的各进程。在因特网中不同计算机的相同端口号是没有联系的。
常用的熟知端口号
应用程序 | FTP | TELNET | SMTP | DNS | TFTP | HTTP | SNMP | HTTPS | SNMP(trap) |
---|---|---|---|---|---|---|---|---|---|
熟知端口号 | 21 | 23 | 25 | 53 | 69 | 80 | 161 | 443 | 162 |
应用层协议与服务的关系:
服务运行后再TCP或UDP的某个端口监听客户端的请求
netstat -an 可查看当计算机当前监听的端口
使用telnet IP地址 端口号 可用来测试端口的畅通性,端口代表是否能访问相应服务。
Windows防火墙的作用:
防火墙将所有的端口都关闭,这时外部无法使用服务来访问计算机,这样可以防止黑客的入侵,但是本机仍然可以与外界联系
用户数据报协议UDP只在IP数据报服务之上增加了复用和分用(也就是端口功能)及差错检验功能。
特点:
用户数据报 UDP 有两个字段:数据字段和首部字段。首部字段有 8 个字节,由 4 个字段组成,每个字段都是两个字节。
UDP用户数据报之前增加12字节的伪首部,在计算检验和时,临时把“伪首部”和 UDP 用户数据报连接在一起。伪首部仅仅是为了计算检验和。
TCP与应用程序的交互是一次一个数据块(大小不定),TCP将应用程序交下来的数据看成是一连串的无结构的字节流,并且TCP不保证接收方应用程序所收到的数据块和发送方应用程序所发出的数据块具有对应大小的关系,但是接收方应用程序收到的字节流必须与发送的一致。也就是过程中的数据分块可以多样,但是最终的结果是传输数据完整一致。
注意:
TCP 把连接作为最基本的抽象,每一条 TCP 连接有两个端点。TCP 连接的端点叫做套接字(socket)或插口。
端口号拼接到(contatenated with) IP 地址即构成了套接字。每一条 TCP 连接唯一地被通信两端的两个端点(即两个套接字)所确定。
套接字 (socket):
在全双工通信时双方既是发送方也是接收方,这里我们仅考虑A发送数据B接收数据,因此A为发送方,B为接收方。
无差错情况
A向B发送M1,发送完停止发送,B收到M1就向A发送确认,A收到确认继续发送M2,同样收到B的确认后发送M3,如此往复。
出现差错
当A发送M1之后,B收到M1后检验出现错误而丢弃了M1(但是没有通知A收到有差错数据),A超过一段时间没有收到确认,就会重新传M1,这就是超时重传,实现超时重传用到了超时计时器。
注意:
确认丢失
当B向A发送的对M1的确认丢失了,A在超时计时器到期后未收到M1的确认,于是A会重传M1,此时B收到M1后,会丢弃重复的这个M1,然后再次向A发送M1的确认。
确认迟到
同样B收到M1后发送M1的确认,但是M1因为网络等等原因并未及时被A收到,这时A有重传了M1,B收到后同样是丢弃重复的M1并再次发送M1的确认。
使用上述的确认和重传机制,我们就可以在不可靠的传输网络上实现可靠的通信。这种可靠传输协议常称为自动重传请求ARQ (Automatic Repeat reQuest)。ARQ 表明重传的请求是自动进行的。接收方不需要请求发送方重传某个出错的分组 。
停止等待协议的优点是简单,但缺点是信道利用率太低。
信道利用率计算式:
为了提高传输效率,可以采用流水线传输:
发送方可连续发送多个分组,不必每发完一个分组就停顿下来等待对方的确认。由于信道上一直有数据不间断地传送,这种传输方式可获得很高的信道利用率。
设置一个发送窗口,实质就是一个数字,如下图的连续将五个分组发送出去而不等待对方确认,当发送方每接收一个确认,发送窗口就向前滑动一个分组的位置。
累积确认:
接收方通常采用累积确认的方式,收到几个分组后将最后一个分组发送确认,表示这个分组之前的所有分组都已确认。
优点:容易实现,即使确认丢失也不必重传。
缺点:不能向发送方反映出接收方已经正确收到的所有分组的信息。
TCP 可靠通信的具体实现
TCP首部前20个字节是固定的,后面为可选字段,因此TCP首部最小长度20字节。
首部固定字段意义:
为方便讨论,这里我们假定数据传输只在一个方向进行(实际一般都是双向进行的)
假设A收到B发送的确认报文段,得知B的接收窗口是20,确认号是31,于是A就将发送窗口设为20,然后向B发送31以后的大小不定的报文段,直到发送窗口的字节发送完毕,B收到A发送的报文段,累积一定的字节(假设为10字节)就会发送确认信息并加上确认号41,发送完确认信息软件就能从接收缓存读取接收的报文段,并且接收窗口会往后移动,A收到确认信息同样发送窗口也会往后移动。
P3 – P1 = A 的发送窗口(又称为通知窗口)
P2 – P1 = 已发送但尚未收到确认的字节数
P3 – P2 = 允许发送但尚未发送的字节数(又称为可用窗口)
A 收到新的确认号,发送窗口向前滑动:
A 的发送窗口内的序号都已用完,但还没有再收到确认,必须停止发送。
发送缓存与接收缓存的作用
发送缓存用来暂时存放:
接收缓存用来暂时存放:
重传机制是 TCP 中最重要和最复杂的问题之一。TCP 每发送一个报文段,就对这个报文段设置一次计时器。只要计时器设置的重传时间到但还没有收到确认,就要重传这一报文段。
加权平均往返时间
TCP 保留了 RTT 的一个加权平均往返时间 RTTS(这又称为平滑的往返时间)。第一次测量到 RTT 样本时,RTTS 值就取为所测量到的 RTT 样本值。以后每测量到一个新的 RTT 样本,就按下式重新计算一次 RTTS:
新的 RTTS = (1 − α) x (旧的 RTTS) + α x (新的 RTT 样本)
0< α < 1。若 α 很接近于零,表示 RTT 值更新较慢。若选择 α 接近于 1,表示 RTT 值更新较快。RFC 2988 推荐的 α 值为 1/8,即 0.125。
当收到的报文段无差错,只是未按序号,就可以采用确认选择作为一种处理方法:
如图所示前面是连续的字节流,但是出现了两个字节快并未按顺序接收到,这里就使用了指针进行标记边界,L表示左边界,也就是字节块第一个字节,R表示右边界,这里说明是字节块最后一个字节的后一位。通过这两个指针就可以将信息发送给发送方,说明已经接受到了这个字节块。
流量控制(flow control)就是让发送方的发送速率不要太快,既要让接收方来得及接收,也不要使网络发生拥塞。利用滑动窗口机制可以很方便地在 TCP连接上实现流量控制。
通过滑动窗口机制可以动态调整双方的发送与接收窗口,从而不至于一次性发送大量数据而导致接收方处理不过来。
A与B建立连接,B告诉A它的接收窗口rwnd是400字节
发送方一直等待接收方的确认信息,但是确认报文段可能中通丢失,这样A一直等待B的确认,B一直等待A发送数据,产生相互等待的死锁。为了解决这个问题
TCP 为每一个连接设有一个持续计时器,只要 TCP 连接的一方收到对方的零窗口通知,就启动持续计时器。若持续计时器设置的时间到期,就发送一个零窗口探测报文段(仅携带 1 字节的数据),而对方就在确认这个探测报文段时给出了现在的窗口值。若窗口仍然是零,则收到这个报文段的一方就重新设置持续计时器。 若窗口不是零,则死锁的僵局就可以打破了。
在某段时间,若对网络中某资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏——产生拥塞(congestion)
出现资源拥塞的条件:
对资源需求的总和 > 可用资源
拥塞控制与流量控制的关系:
TCP拥塞控制算法有四种:
拥塞控制也叫做基于窗口的拥塞控制,发送方维持一个叫做拥塞窗口 cwnd (congestionwindow)的状态变量。
慢开始算法的原理:增大发送端的拥塞窗口cwnd,可以使分组注入到网络的速率更加合理。使用慢开始算法后,没经过一个传输轮次,拥塞窗口cwnd就加倍。
为了防止拥塞窗口cwnd增长过大引起网络拥塞,需要设置一个慢开始门限ssthresh状态变量,慢开始用法如下:
乘法减小(multiplicative decrease)
“乘法减小“是指不论在慢开始阶段还是拥塞避免阶段,只要出现一次超时(即出现一 次 网 络 拥 塞 ) , 就 把 慢 开 始 门 限 值ssthresh 设置为当前的拥塞窗口值乘以0.5。当网络频繁出现拥塞时,ssthresh 值就下降得很快,以大大减少注入到网络中的分组数。
加法增大(additive increase)
“加法增大”是指执行拥塞避免算法后,在收到对所有报文段的确认后(即经过一个往返时间),就把拥塞窗口 cwnd增加一个MSS 大小,使拥塞窗口缓慢增大,以防止网络过早出现拥塞。
快重传算法首先要求接收方每收到一个失序的报文段后就立即发出重复确认。这样做可以让发送方及早知道有报文段没有到达接收方。发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段。
快恢复算法
(1) 当发送端收到连续三个重复的确认时,就执行“乘法减小”算法,把慢开始门限 ssthresh减半。但接下去不执行慢开始算法。
(2)由于发送方现在认为网络很可能没有发生拥塞,因此现在不执行慢开始算法,即拥塞窗口cwnd 现在不设置为 1,而是设置为慢开始门限 ssthresh 减半后的数值,然后开始执行拥塞避免算法(“加法增大”),使拥塞窗口缓慢地线性增大。
发送窗口的上限值
发送方的发送窗口的上限值应当取为接收方窗口rwnd 和拥塞窗口 cwnd 这两个变量中较小的一个,即应按以下公式确定:
发送窗口的上限值 = Min [rwnd, cwnd]
运输连接有三个阶段:
TCP 连接的建立都是采用客户服务器方式。主动发起连接建立的应用进程叫做客户(client)。被动等待连接建立的应用进程叫做服务器(server)。
TCP建立连接的过程叫握手,握手需要客户与服务器之间交换三个TCP报文段。
下面是三次握手的内容(ACK:确认位,SYN:同步位,seq:序号,表示报文段数据的第一个字节,ack:确认号,表示希望收到对方下一个报文段的第一个数据字节序号)
为什么前两次已经建立连接,仍然需要第三次握手?
假定出现这种情况:A发送了第一个请求连接,请求报文段并未丢失,而是在网络中滞留了一段时间,A因为没收到确认报文,于是重传了一次连接请求,然后与B正常建立了连接,这时B收到了A第一次发送的请求报文因为A又发了一次新的连接请求,于是向A发送确认报文段,同意建立连接。假如没有第三次握手,B发出确认后,连接已经建立。但是A并未请求新的连接,于是会丢弃B的确认报文,而B因为新的连接已经建立,一直等待A发送数据,这样就造成B的许多资源浪费。
传输结束后,双方可释放连接,选择A和B都处于ESTABLSHED状态(终止位FIN同样不携带数据,但是要消耗一个序号)
下面是四次挥手过程:
为什么A进入TIME-WAIT必须等待 2MSL 的时间?