TPC/UDP协议学习笔记
TPC和UDP协议
OSI七层模型和TCP/IP四层模型
- 应用层
- 表示层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理层
TCP/IP 四层概念:
- 应用层:应用层、表示层、会话层:HTTP
- 传输层:传输层:TCP/UDP
- 网络层:网络层:IP
- 数据链路层:数据链路层、物理层
什么是TCP
TCP协议简单来说是一种位于传输层的,面向连接
的、可靠的、基于字节流的传输层通信协议
TCP的特点
- TCP是
面向连接
的传输层协议。比如说TCP的三次握手,四次分手,针对的都是连接。而 UDP 没有相应建立连接的过程,只是一直在发送数据。 - 每一条TCP连接
只能有两个端点
,每一条TCP连接是点对点的。也就是说TCP是不同计算机之间的进程的通信
。 - TCP提供可靠交付的服务,无差错,不丢失,不重复,按序到达。总结一下就是,
可靠有序,不丢不重
。 - TCP提供
全双工通信
。全双工指的是连接双方可以同时收发数据。在收发两端都有发送缓存和接收缓存,发送缓存就是一个准备发送的队列,接收缓存是一个准备接收的队列。 - 有状态,TCP 会精准记录哪些数据发送了,哪些数据被对方接收了,哪些没有被接收到,而且保证数据包按序到达,不允许半点差错。这是有状态。
- 可控制,当意识到丢包了或者网络环境不佳,TCP 会根据具体情况调整自己的行为,控制自己的发送速度或者重发。这是可控制。
什么是UDP
UDP协议是一种无连接
的传输层协议,提供面向事务的简单不可靠信息传送服务。
UDP的特点
UDP是
无连接的
,减少开销和发送数据之前的时间延迟。大家都知道TCP
的三次握手和四次分手
,这个是需要时间花销的,但是UDP没有这部分花销。UDP使用
最大努力交付
,即不保证可靠交付。那谁来保证可靠的交付呢?是由UDP的上一层协议,应用层来保证。UDP是
面向报文的
,适合一次性传输少量数据的网络应用。什么意思呢,如下图,UDP这层,把应用层的全部内容作为自己的数据报部分,在IP层也只是加了一个IP首部,我们知道,在以太网,链路层上的数据如果超过1500字节,就会分片,所以网络层发现上面传输层给了太大的数据就会分片
,加上UDP是不可靠的协议,这就加大了UDP的不可靠性
,容易丢失,所以UDP适合数据量少的。
UDP没有拥塞控制,适合很多实时应用。也就是说如果网络堵塞,UDP不管那么多,照样按照自己的速率发数据,那有些人就会说,这协议是不是有点坑B,路都堵上了,还发死劲发数据呢,但是反过来看,这也是UDP的优点,它允许丢包,如果你的网络情况还不错,UDP就非常适合实时应用,比如视频会议。
UDP首部较小,只有8字节,而TCP由有·0字节。这也是
减少网络传输开销
的一方面。
TCP的三次握手
TCP 的三次握手,是为了需要确认双方的两样能力: 发送的能力
和接收的能力
。
tpc的报文中,有6个控制位:
控制位 | 作用 |
---|---|
ACK | 置1时表示确认号合法,为0的时候表示数据段不包含确认信息,确认号被忽略 |
PSH | 置1时请求的数据段在接收方得到后就可直接送到应用程序,而不必等到缓冲区满时才传送 |
RST | 置1时重建连接。如果接收到RST位时候,通常发生了某些错 |
SYN | 置1时用来发起一个连接 |
FIN | 置1时表示发端完成发送任务。用来释放连接,表明发送方已经没有数据发送了 |
URG | 紧急指针,告诉接收TCP模块紧要指针域指着紧要数据 |
第一步:发送方发送一个数据包给接收方,接收方确认发送方的发送能力
客户端要发送一个数据包告诉服务器要建立连接,根据上面我们了解到的控制位信息,建立连接需要把SYN置为1
,seq
指的是序号,是随机产生的。
第二步:接收方返回一个确认报文给发送方,发送方确认接收方的发送和接收能力
服务器收到该数据包后,会为该TCP连接分配缓存和变量
,缓存指的是一个字节流队列。(发送方和接收方都有这个队列,而且如果双方需要互相通信,那么双方都会有发送缓存和接收缓存),接着会返回一个确认报文,其中SYN控制位置为1
,意思是允许建立连接,ACK是确认号
,确认收到了发送方的包,并且会设一个seq序号
,也为一个随机数。小写ack
是确认号,也就是接下来希望发送方要发的数据从发送方发送到的seq序号+1
开始。
第三步:发送方发送确认给接收方,接收方确认了发送方的接收能力
客户端需要给服务器端返回一个确认,此时SYN控制位变为0
,意思这不是建立连接的请求了,要正式发数据了,ACK是确认码
,意思是收到了服务器的确认请求了。小写ack
是确认号,也就是接下来希望接收方要发的数据从接收方返回的seq序号+1
开始。
TCP的四次挥手
第一步:客户端发起请求,请求断开链接。FIN=1,seq=u
。u是之前传送过来的最后一个字节的序号+1
第二步:服务器收到客户端的请求断开链接的报文之后,返回确认信息。ACK=1,seq=v,ack=u+1
。这个时候,客户端不能给服务器发送信息报文,只能接收。但是服务器要是还有信息要传给服务器,仍然能传送。这里的v
是什么意思呢,这就取决于服务器发送给客户端之前的一个包确认号是多少了。
第三步:当服务器也没有了可以传的信息之后,给客户端发送请求结束的报文。FIN=1,ACK=1,ack=u+1,seq=w
。这里的w
,跟上面的v
是一个意思,为什么不都是v
呢,因为这一步和上一步中间可能还在发数据呢,所以seq
这个数据发送的字节流序号可能要变。
第四步:客户端接收到FIN=1
的报文之后,返回确认报文,ACK=1,seq=u+1,ack=w+1
。发送完毕之后,客户端进入等待状态,等待两个时间周期。关闭
常见问题
三次握手
为什么不能用两次握手进行连接?
无法确认客户端的接收能力。
可能造成的问题:
若建立连接只需两次握手,客户端并没有太大的变化,仍然需要获得服务端的应答后才进入
ESTABLISHED
状态,而服务端在收到任意连接请求后就进入ESTABLISHED
状态。如果此时网络拥堵,客户端收到的发送请求迟迟到不了服务端,客户端便超时重发请求,双方便开始通信,通信结束后释放连接。此时如果之前那个迟迟到不了服务端,滞留在网路中的请求到达了服务端,由于只有两次握手,服务端收到请求就会进入
ESTABLISHED
状态,等待发送数据或主动发送数据。但这时客户端已经关闭,服务端就会一直等待下去,浪费服务端连接资源。在第二次握手时,服务器对客户端发送的序列号做了确认,第三次握手时,客户端对服务器的序列号做确认,如果没有第三次握手,则不能保证传输的可靠性。
三次握手过程中可以携带数据吗?
第三次握手的时候,可以携带。前两次握手不能携带数据。
如果前两次握手能够携带数据,那么一旦有人想攻击服务器,那么他只需要在第一次握手中的 SYN 报文中放大量数据,那么服务器势必会消耗更多的时间和内存空间去处理这些数据,增大了服务器被攻击的风险。
第三次握手的时候,客户端已经处于ESTABLISHED
状态,并且已经能够确认服务器的接收、发送能力正常,这个时候相对安全了,可以携带数据。
什么是SYN洪泛攻击?
SYN洪泛攻击就是利用TCP协议的特性(三次握手)。
攻击者发送TCP的 SYN
,SYN是TCP三次握手中第一个数据包,而当服务器返回ACK后,该攻击者就不对其进行再确认,那这个TCP连接就处于挂起状态,也就是半连接状态,服务器收不到再确认的话,还会重复发送ACK给攻击者。
这样更加会浪费服务器资源。攻击者就对服务器发送大量的这种TCP连接,由于每一个连接都无法完成三次握手,所以就在服务器上,这些TCP连接会因为挂起状态而消耗CPU和内存,最后服务器可能死机。
如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP保活计时器 每次客户端请求服务器会重置计时器,当2小时之内
没收到客户端任何数据时,会每隔75s
向客户端发一个探测报文,若接连发送10个
,客户端都没有反应,则认为客户端故障,关闭连接。
四次挥手
为什么最后还要等待两个时间周期呢?
可能造成的问题:
如果客户端的最后一个
ACK
报文在传输的时候丢失,服务器并没有接收到这个报文。这个候时候服务器就会超时重传这个FIN
消息,然后客户端就会重新返回最后一个ACK报文
,等待两个时间周期,完成关闭。如果不等待这两个时间周期,客户端直接关闭,服务器重传的那条消息就不会收到。服务器就因为接收不到客户端的信息而无法正常关闭。
如果不等待,客户端直接跑路,当服务端还有很多数据包在路上的时候,若客户端的端口此时刚好被新的应用占用,那么就接收到了无用数据包,造成数据包混乱。所以,最保险的做法是等服务器发来的数据包都死翘翘再启动新的应用。
1 个 时间周期确保四次挥手中主动关闭方最后的 ACK 报文最终能达到对端
1 个 时间周期确保对端没有收到 ACK 重传的 FIN 报文可以到达
为什么是四次挥手而不是三次?
因为服务端在接收到FIN
, 仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以服务端可以立即关闭,也可以发送一些数据给对方后,再发送FIN
报文给对方来表示同意现在关闭连接。因此先发一个ACK
表示已经收到客户端的FIN
,等服务端所有数据都发出去了才发FIN
。这就造成了四次挥手。
如果是三次挥手,等于说服务端将ACK
和FIN
的发送合并为一次挥手,这个时候长时间的延迟可能会导致客户端误以为FIN
没有到达客户端,从而让客户端不断的重发FIN
。
第二次挥手和第三次挥手之间,如果服务端还需要向客户端发送数据,这时在第二次挥手和第三次挥手合并的情况下,可能会导致服务端还没发送完,客户端就已经关闭。
TCP/UDP协议
TCP如何实现可靠传输?
主要通过以下四种方式实现可靠传输机制:
- 校验:伪首部是为了增加TCP校验和的检错能力:通过伪首部的目的IP地址来检查TCP报文是否收错了、通过伪首部的传输层协议号来检查传输层协议是否选对了。需要注意的是,伪首部实际上是不存在的,只是用来验证TCP报文是否出错。
- 序号:之前我们提到TCP是面向字节流的,比如第一个字节就是序号1,第二个字节就是序号2。 而在TCP报文格式,有一个序号字段,这个指的是一个报文段第一个字节的序号。报文段就是你每个数据包。有了序号,就能保证数据是有序的传入应用层。
- 确认:发送方在收到接收方的确认包之后,才继续发送剩下的数据。
- 重传:TCP的发送方在规定的时间内没有收到确认就要重传已发送的报文段(超时重传)。重传时间是动态改变的,依据的是RTTS(加权平均往返时间)。
TCP和UDP的区别
TCP是面向连接的,udp是无连接的即发送数据前不需要先建立链接。
TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,
可靠有序,不丢不重
;UDP尽最大努力交付,不保证可靠交付
。 并且因为tcp可靠,面向连接,不会丢失数据因此适合大数据量的交换。TCP是面向字节流,UDP面向报文,并且网络出现拥塞不会使得发送速率降低(因此会出现丢包,对实时的应用比如IP电话和视频会议等)。
TCP只能是1对1的传输,UDP支持1对1,1对多。
TCP的首部较大为20字节,而UDP只有8字节。