文章目录
概念先整清楚
TCP协议和UDP协议与TCP/IP协议的联系
TCP/IP协议
是一个协议簇
,里面包括很多协议的,UDP只是其中的一个,之所有命名为TCP/IP协议
,因为TCP、IP协议是两个很重要的协议 ,所以就用他们命名了
TCP/IP协议簇
包括应用层、传输层、网络层、网络访问层
-
应用层包括:
- 超文本传输协议 HTTP,万维网的基本协议。
- 文件传输 TFTP。
- 远程登录 Telnet,提供远程访问其他主机功能。
- 网络管理 SNMP 简单网络管理协议,该协议提供了监控网络设备的方法,以及配置管理,统计信息收集,性能管理及安全管理等;
- 域名系统 DNS , 将域名转换成IP地址
-
传输层包括
- TCP,面向连接的TCP传输控制协议,列举一些运行在TCP协议上的应用层协议
- HTTP,主要用于普通浏览。
- HTTPS , 安全超文本传输协议,HTTP协议的安全版本
- FTP,文件传输协议,用于文件传输。
- POP3,邮局协议,收邮件用。
- SMTP,简单邮件传送协议,用来发送电子邮件
- TELNET,通过一个终端terminal登录到网络。
- SSH,用于替代安全性差的TELNET,用于加密安全登录用。
- UDP,无连接的包传输的UDP用户数据报文协议,列举一些运行在UDP协议上的应用层协议:
- BOOTP,启动协议,应用于无盘设备
- NTP,网络时间协议,用于网络同步
- DHCP,动态主机配置协议,动态配置IP地址
- DCCP 数据拥塞控制协议
- SCTP 流控制传输协议
- TCP,面向连接的TCP传输控制协议,列举一些运行在TCP协议上的应用层协议
-
网络层包括
- Internet协议,IP协议。
- Internet控制信息协议,ICMP。
- 地址解析协议,ARP。
- 反向地址解析协议,RARP。
-
网络访问层(主机到网络层 , host-to-network)
TCP/IP四层模式里最后一层对应OSI七层里的数据链路层和物理层,主要功能包括IP地址与物理地址硬件的映射,以及将IP数据报封装成帧。
TCP和UDP区别 (面试常问)
关于这个问题,我也被问了好几次了,每次都答不完整,在这里好好整理一下,方便查阅。
- TCP,是面向连接;
- UDP,是无连接。
- TCP,点对点全双工通信;
- UDP,一对一、一对多(广播)、多对一、多对多的交互通信。
- TCP,面向字节流(把上层即应用层传下来的报文看出字节流,然后组织成大小不等数据块);
- UDP,面向报文(对报文不合并也不拆分,只添加UDP首部8字节)。
- TCP,是可靠的(无差错,不丢失,不重复,概括保证数据正确性,且按序到达);
- UDP,尽最大可能交付的(是不可靠的)。
- TCP,有拥塞控制、流量控制(下面会说明);
- UDP,没有拥塞控制,即如果网络出现拥塞,也不会让发送方主机降低发送速率;视频传输(在线视频)、实时通信(QQ聊天)、语言传输(电话),对数据准确性和丢包要求比较低,但速度必须快的。
TCP & UDP 特点
- 传输控制协议 TCP(Transmission Control Protocol)是
面向连接的
,提供可靠交付
,有流量控制,拥塞控制
,提供全双工通信
,面向字节流
(把应用层传下来的报文看成字节流,把字节流组织成大小不等的数据块),每一条 TCP 连接只能是点对点
的(一对一)。 - 用户数据报协议 UDP(User Datagram Protocol)是
无连接的
,尽最大可能交付
,没有拥塞控制
,面向报文
(对于应用程序传下来的报文不合并也不拆分,只是添加 UDP 首部),支持一对一、一对多、多对一和多对多的交互通信
。
TCP 首部格式
-
序号 :用于对字节流进行编号,例如序号为 301,表示第一个字节的编号为 301,如果携带的数据长度为 100 字节,那么下一个报文段的序号应为 401。
-
确认号 :期望收到的下一个报文段的序号。例如 B 正确收到 A 发送来的一个报文段,序号为 501,携带的数据长度为 200 字节,因此 B 期望下一个报文段的序号为 701,B 发送给 A 的确认报文段中确认号就为 701。
-
数据偏移 :指的是数据部分距离报文段起始处的偏移量,实际上指的是首部的长度。
-
确认 ACK :当 ACK=1 时确认号字段有效,否则无效。TCP 规定,在连接建立后所有传送的报文段都必须把 ACK 置 1。
-
同步 SYN :在连接建立时用来同步序号。当 SYN=1,ACK=0 时表示这是一个连接请求报文段。若对方同意建立连接,则响应报文中 SYN=1,ACK=1。
-
终止 FIN :用来释放一个连接,当 FIN=1 时,表示此报文段的发送方的数据已发送完毕,并要求释放连接。
-
窗口 :窗口值作为接收方让发送方设置其发送窗口的依据。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。
UDP 首部格式
首部字段只有 8 个字节,包括源端口、目的端口、长度、检验和。12 字节的伪首部是为了计算检验和临时添加的。
TCP如何保证可靠传输的?
这里给个答案(来自TCP 协议如何保证可靠传输)
-
确认和重传:接收方收到报文就会确认,发送方发送一段时候后没有收到确认就重传
-
数据校验
-
数据合理分片和排序:
- UDP:IP数据报大于1500字节,大于MTU.这个时候发送方IP层就需要分片(fragmentation).把数据报分成若干片,使每一片都小于MTU.而接收方IP层则需要进行数据报的重组.这样就会多做许多事情,而更严重的是,由于UDP的特性,当某一片数据传送中丢失时,接收方便无法重组数据报.将导致丢弃整个UDP数据报.
- tcp会按MTU合理分片,接收方会缓存未按序到达的数据,重新排序后再交给应用层。
-
流量控制:当接收方来不及处理发送方的数据,能提示发送方降低发送的苏丽,防止包丢失
-
拥塞控制:当网络拥塞时,降低发送速率。
TCP流量控制
可以用一句话概括,流量控制是为了控制发送方发送速率,保证接收方来得及接收。
怎么实现的呢?↓
接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。
将窗口字段设置为 0,则发送方不能发送数据。如果接收方有足够大的接收缓存,就不会发生流量控制;
如何实现流量控制 ?
TCP中由滑动窗口协议(连续ARQ协议)实现
。滑动窗口协议既保证了分组无差错、有序接收,也实现了流量控制。主要的方式就是接收方返回的 ACK 中会包含自己的接收窗口的大小,并且利用大小来控制发送方的数据发送。
流量控制引发的死锁?
当发送者收到了一个窗口为0的应答,发送者便停止发送,等待接收者的下一个应答。但是如果这个窗口不为0的应答在传输过程丢失,发送者一直等待下去,而接收者以为发送者已经收到该应答,等待接收新数据,这样双方就相互等待,从而产生死锁。
怎么避免死锁的发生?
为了避免流量控制引发的死锁,TCP使用了持续计时器
。每当发送者收到一个0窗口的应答后就启动该计时器
。时间一到便主动发送报文询问接收者的窗口大小。若接收者仍然返回零窗口,则重置该计时器继续等待;若窗口不为0,则表示应答报文丢失了,此时重置发送窗口后开始发送,这样就避免了死锁的产生。
TCP拥塞控制
如果网络出现拥塞,分组将会丢失,此时发送方会继续重传,从而导致网络拥塞程度更高。因此当出现拥塞时,应当控制发送方的速率。这一点和流量控制很像,但是出发点不同。流量控制是为了让接收方能来得及接收,而拥塞控制是为了降低整个网络的拥塞程度。
TCP 主要通过四个算法来进行拥塞控制:慢开始、拥塞避免、快重传、快恢复。
慢开始与拥塞避免
先了解一波名词
- cwnd ,拥塞窗口
- ssthresh ,处理拥塞时参照的一个参数
虽然 TCP 的窗口基于字节,但是这里设窗口的大小单位为报文段。
发送的最初执行慢开始,令 cwnd = 1,发送方只能发送 1 个报文段;当收到确认后,将 cwnd 加倍,因此之后发送方能够发送的报文段数量为:2、4、8 …
注意到慢开始每个轮次都将 cwnd 加倍,这样会让 cwnd 增长速度非常快,从而使得发送方发送的速度增长速度过快,网络拥塞的可能性也就更高。设置一个慢开始门限 ssthresh,当 cwnd >= ssthresh 时,进入拥塞避免,每个轮次只将 cwnd 加 1。
如果出现了超时,则令 ssthresh = cwnd / 2,然后重新执行慢开始。
快重传和快恢复
-
在接收方,要求每次接收到报文段都应该对最后一个已收到的有序报文段进行确认。例如已经接收到 M1 和 M2,此时收到 M4,应当发送对 M2 的确认。
-
在发送方,
如果收到三个重复确认,那么可以知道下一个报文段丢失
,此时执行快重传,立即重传下一个报文段。例如收到三个 M2,则 M3 丢失,立即重传 M3。 -
在这种情况下,只是丢失个别报文段,而不是网络拥塞。因此执行快恢复,令 ssthresh = cwnd / 2 ,cwnd = ssthresh,注意到此时直接进入拥塞避免。
-
慢开始
和快恢复
的快慢指的是cwnd
的设定值,而不是cwnd
的增长速率。慢开始 cwnd 设定为 1,而快恢复 cwnd 设定为 ssthresh。
TCP 的三次握手
假设 A 为客户端,B 为服务器端。
-
首先 B 处于
LISTEN(监听)状态
,等待客户的连接请求。 -
A 向 B 发送连接请求报文,
SYN = 1,ACK=0,选择一个初始的序号x(seq = x)
-
B 收到连接请求报文,如果同意建立连接,则向A发送连接确认报文,
SYN =1 ,ACK= 1,确认号为x+1 (ack = x + 1),seq = y
-
A 收到B的连接确认报文后,还要向B发出确认,
ACK = 1 ,确认号为y+1(ack = y +1 ),序号为x+1(seq = x +1)
-
B收到A 的确认后,连接建立。
为什么要三次才建立连接?
第三次握手是为了防止失效的连接请求到达服务器,让服务器错误打开连接。
客户端发送的连接请求如果在网络中滞留,那么就会隔很长一段时间才能收到服务器端发回的连接确认。客户端等待一个超时重传时间之后,就会重新请求连接。但是这个滞留的连接请求最后还是会到达服务器,如果不进行三次握手,那么服务器就会打开两个连接。如果有第三次握手,客户端会忽略服务器之后发送的对滞留连接请求的连接确认,不进行第三次握手,因此就不会再次打开连接。
TCP四次挥手
- A发送连接释放报文
FIN = 1 ,seq = u
- B收到之后发出确认,此时TCP属于半关闭状态,B 能向A发送数据但是A不能向B发送数据
ACK = 1 ,ack = u + 1,seq = v
- 当B 不再需要连接时,发送连接释放报文,
FIN =1 ,ACK = 1 ,ack = u + 1 ,seq = w
- A收到后发出确认,进入
TIMEE-WAIT
状态,等待2MSL (最大报文存活时间)
后释放连接。ACK= 1,ack = w + 1 ,seq = u + 1
- B收到A的确认后释放连接。
四次挥手的原因
简单来说,就是为了,让服务器发送完所有数据后,再关闭连接。
客户端发送了FIN连接数据报文之后,服务器收到这个报文,就进入了CLOSE-WAIT状态。这个状态是为了让服务器发送还未传送完毕的数据,传送完毕之后,服务器会发送FIN连接释放报文。
TIME_WAIT(面试问过)
该词是,客户端收到服务器端FIN报文(连接释放报文)进入该状态,下一个阶段就是CLOSE阶段,就是真正上的关闭连接了。但是不能关闭,必须等待2MSL
时间。这么做有两个原因:
- 确保最后一个确认报文能够到达,如果B没收到A的确认报文,就会超时重发(连接释放报文),TIME_WAIT状态就是为了处理这种情况发生。
- 根据上面原因可知,为了保证在新的连接请求中不会出现上一次的请求报文。
补充
-
MSL
: Maximum Segment Lifetime,译为“报文最大生存时间”,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。因为TCP报文段以IP数据报在网络内传输,而IP数据报则有限制其生存时间的TTL字段
。 -
在
TIME_WAIT状态
时两端的端口不能使用,要等到2MSL时间结束才可继续使用。 -
当连接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。不过在实际应用中可以通过设置SO_REUSEADDR选项达到不必等待2MSL时间结束再使用此端口。
-
RFC 793中规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等
滑动窗口(TCP可靠传输的具体实现)
- 为什么要使用滑动窗口?
- 窗口是什么?
- 怎么确认?(累计确认)
- 发送方收到确认时怎么处理?
- 什么时候重传?
↓↓↓↓↓↓
窗口是缓存的一部分,用来暂时存放字节流。发送方和接收方各有一个窗口,接收方通过 TCP 报文段中的窗口字段告诉发送方自己的窗口大小,发送方根据这个值和其它信息设置自己的窗口大小(发送窗口的大小swnd=min(rwnd,cwnd)
。rwnd是接收窗口,cwnd用于拥塞控制)。
- 发送窗口内的字节都允许被发送,接收窗口内的字节都允许被接收。
- 如果发送窗口左部的字节已经发送并且收到了确认,那么就将发送窗口向右滑动一定距离,直到左部第一个字节不是已发送并且已确认的状态;
- 接收窗口的滑动类似,接收窗口左部字节已经发送确认并交付主机,就向右滑动接收窗口。
如图,接收窗口只会对窗口内最后一个按序到达的字节进行确认(发送确认),例如接收窗口已经收到的字节为 {31, 34, 35},其中 {31} 按序到达,而 {34, 35} 就不是,因此只对字节 31 进行确认。发送方得到一个字节的确认之后,就知道这个字节之前的所有字节都已经被接收。
TCP的超时重传
超时重传:如果一个已经发送的报文段在超时时间内没有收到确认,那么就重传这个报文段
一个报文段从发送再到接收到确认所经过的时间称为往返时间 RTT
,加权平均往返时间 RTTs
计算如下:
超时时间 RTO 应该略大于 RTTs,TCP 使用的超时时间计算如下:
RTTd 为偏差
整理目前比较欠缺的知识。