传输层协议TCP, 传输控制协议
UDP,用户数据报协议 无连接,尽最大努力交付
TCP
TCP 特性TCP 提供一种面向连接的、可靠的字节流服务
在一个 TCP 连接中,仅有两方进行彼此通信。广播和多播不能用于 TCP
TCP 使用校验和,确认和重传机制来保证可靠传输
TCP 给数据分节进行排序,并使用累积确认保证数据的顺序不变和非重复
TCP 使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制
1
2
3
4
注意:TCP 并不能保证数据一定会被对方接收到,因为这是不可能的。TCP 能够做到的是,
如果有可能,就把数据递送到接收方,否则就(通过放弃重传并且中断连接这一手段)通知用
户。因此准确说 TCP 也不是 100% 可靠的协议,它所能提供的是数据的可靠递送或故障的
可靠通知。
面向连接
TCP 常用标志位1
2
3
4
5
SYN(synchronous建立联机)
ACK(acknowledgement 确认)
FIN(finish结束)
Sequence number(顺序号码)
Acknowledge number(确认号码)
数据传输开始之前,需要建立连接 (三次握手)。 数据传输结束之后,需要释放连接 (四次挥手)
TCP 可靠传输的精髓
TCP 连接的一方 A,由操作系统动态随机选取一个 32 位长的序列号(Initial Sequence Number),假设 A 的初始序列号为 1000,以该序列号为原点,对自己将要发送的每个字节的数据进行编号,1001,1002,1003…,并把自己的初始序列号 ISN 告诉 B,让 B 有一个思想准备,什么样编号的数据是合法的,什么编号是非法的,比如编号 900 就是非法的,同时 B 还可以对 A 每一个编号的字节数据进行确认。如果 A 收到 B 确认编号为 2001,则意味着字节编号为 1001-2000,共 1000 个字节已经安全到达。
同理 B 也是类似的操作,假设 B 的初始序列号 ISN 为 2000,以该序列号为原点,对自己将要发送的每个字节的数据进行编号,2001,2002,2003…,并把自己的初始序列号 ISN 告诉 A,以便 A 可以确认 B 发送的每一个字节。如果 B 收到 A 确认编号为 4001,则意味着字节编号为 2001-4000,共 2000 个字节已经安全到达。
TCP 连接握手,握的是啥?通信双方数据原点的序列号!
三次握手
建立一个 TCP 连接时,需要客户端和服务器总共发送 3 个包.
三次握手的目的是连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换 TCP 窗口大小信息。
在 socket 编程中,客户端执行 connect() 时。将触发三次握手。
第一次握手 (SYN=1, seq=x)
由客户端向服务端发送 SYN 标志位置 1 的包 ,指明客户端打算连接的服务器的端口,以及初始序号 X。
第二次握手 (SYN=1, ACK=1, seq=y, ACKnum=x+1):
服务器发回确认包 (ACK) 应答。即 SYN 标志位和 ACK 标志位均为 1。服务器端选择自己 ISN 序列号,放到 Seq 域里,同时将确认序号 (Acknowledgement Number) 设置为客户的 ISN 加 1,即 X+1
第三次握手 (ACK=1,ACKnum=y+1)
客户端再次发送确认包 (ACK),SYN 标志位为 0,ACK 标志位为 1,并且把服务器发来 ACK 的序号字段 +1,放在确定字段中发送给对方,并且在数据段放写 ISN 的 +1
为什么是” 三次握手”?
两次握手的过程:
2.1 A 发送同步信号 SYN + A’s ISN(Initial sequence number)
2.2 B 发送同步信号 SYN+B’s ISN+B‘s ACK sequence number
这里有一个问题,A 与 B 就 A 的初始序列号达成了一致,这里是 1000。但是 B 无法知道 A 是否已经接收到自己的同步信号,如果这个同步信号丢失了,A 和 B 就 B 的初始序列号将无法达成一致
如果 A 发给 B 的确认丢了,该如何?
A 会超时重传这个 ACK 吗?不会!TCP 不会为没有数据的 ACK 超时重传。B 如果没有收到 A 的 ACK,会超时重传自己的 SYN 同步信号,一直到收到 A 的 ACK 为止 (SYN 攻击埋下伏笔)。
SYN 攻击
在三次握手过程中,服务器发送 SYN-ACK 之后,收到客户端的 ACK 之前的 TCP 连接称为半连接 (half-open connect)。此时服务器处于 SYN_RCVD 状态。当收到 ACK 后,服务器才能转入 ESTABLISHED 状态.
SYN 攻击指的是,攻击客户端在短时间内伪造大量不存在的 IP 地址,向服务器不断地发送 SYN 包,服务器回复确认包,并等待客户的确认。由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的 SYN 包将长时间占用未连接队列,正常的 SYN 请求被丢弃,导致目标系统运行缓慢,严重者会引起网络堵塞甚至系统瘫痪。
SYN 攻击是一种典型的 DoS/DDoS 攻击。
如何检测 SYN 攻击?
检测 SYN 攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源 IP 地址是随机的,基本上可以断定这是一次 SYN 攻击。在 Linux/Unix 上可以使用系统自带的 netstats 命令来检测 SYN 攻击。
如何防御 SYN 攻击?
SYN 攻击不能完全被阻止,除非将 TCP 协议重新设计。我们所做的是尽可能的减轻 SYN 攻击的危害,常见的防御 SYN 攻击的方法有如下几种:
缩短超时(SYN Timeout)时间
增加最大半连接数
过滤网关防护
SYN cookies 技术
四次挥手
TCP 的连接的拆除需要发送四个包,因此称为四次挥手 (Four-way handshake),也叫做改进的三次握手。客户端或服务器均可主动发起挥手动作,在 socket 编程中,任何一方执行 close() 操作即可产生挥手操作。
为什么要” 四次挥手”
由于 TCP 连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个 FIN 来终止这个方向的连接。收到一个 FIN 只意味着这一方向上没有数据流动,一个 TCP 连接在收到一个 FIN 后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭
TCP 协议的连接是全双工连接,一个 TCP 连接存在双向的读写通道。
简单说来是 “先关读,后关写”,一共需要四个阶段。以客户机发起关闭连接为例:
1.服务器读通道关闭
2.客户机写通道关闭
3.客户机读通道关闭
4.服务器写通道关闭
挥手过程
第一阶段 客户机发送完数据之后,向服务器发送一个 FIN 数据段,序列号为 i;
1.服务器收到 FIN(i) 后,返回确认段 ACK,序列号为 i+1,关闭服务器读通道;
2.客户机收到 ACK(i+1) 后,关闭客户机写通道;
(此时,客户机仍能通过读通道读取服务器的数据,服务器仍能通过写通道写数据)
第二阶段 服务器发送完数据之后,向客户机发送一个 FIN 数据段,序列号为 j;
3.客户机收到 FIN(j) 后,返回确认段 ACK,序列号为 j+1,关闭客户机读通道;
4.服务器收到 ACK(j+1) 后,关闭服务器写通道。
这是标准的 TCP 关闭两个阶段,服务器和客户机都可以发起关闭,完全对称。
可靠传输
TCP 如何保证可靠传输呢?
无差错
不丢失
不重复
面向字节流
不管发送方一次性提交给 TCP 的缓冲是多大的数据,对于 TCP 本身来说它会根据实际的情况来进行划分,比如发送方发送 10 字节,TCP 并不是一次性传递 10 字节数据,它可能是拆分成 3 个字节和 7 个字节分俩次发送给接收方
流量控制
基于滑动窗口协议实现.TCP 的滑动窗口主要有两个作用,一是提供 TCP 的可靠性,二是提供 TCP 的流控特性。同时滑动窗口机制还体现了 TCP 面向字节流的设计思路。
滑动窗口协议是传输层进行流控的一种措施,接收方通过通告发送方自己的窗口大小,从而控制发送方的发送速度,从而达到防止发送方发送速度过快而导致自己被淹没的目的。
对照上图,现在假如发送窗口是客户端,接收窗口是服务端。当我们现在要继续发送数据的时候,可能由于接收方的接收窗口没有那么大,而发送方的发送窗口非常大,就会以更快的速率往后发,需要由接收窗口通过向 TCP 的报文首部字段中去更改窗口值去调整发送方的发送窗口大小。
拥塞控制
慢开始,拥塞避免
快恢复,快重传
横轴代表 APP 交互或者轮循次数,纵轴代表窗口值的大小
上图中,一开始我们可以先发送一个报文,如果没有发生网络拥塞,就继续发送 2 个报文,依然没有发生网络拥塞,就继续翻倍,直到 16 个报文,这就是慢开始算法
当到达 16 报文数的时候,会采用拥塞避免的策略来进行发送报文的一个数量的线性增长。
当报文数到 24 的时候,就会发生网络拥塞,采用拥塞避免的乘法减小到值发送 1 一个报文,来减少对网络层面带来的压力,然后再重新开始 慢开始算法增长,同时限定一个新的门限值.
UDP
UDP 是一个简单的传输层协议。和 TCP 相比,UDP 有下面几个显著特性:
UDP 缺乏可靠性。UDP 本身不提供确认,序列号,超时重传等机制。UDP 数据报可能在网络中被复制,被重新排序。即 UDP 不保证数据报会到达其最终目的地,也不保证各个数据报的先后顺序,也不保证每个数据报只到达一次
UDP 数据报是有长度的。每个 UDP 数据报都有长度,如果一个数据报正确地到达目的地,那么该数据报的长度将随数据一起传递给接收方。而 TCP 是一个字节流协议,没有任何(协议上的)记录边界。
UDP 是无连接的。UDP 客户和服务器之前不必存在长期的关系。UDP 发送数据报之前也不需要经过握手创建连接的过程。
UDP 支持多播和广播。
参考