TCP/IP总结(TCP与UDP区别,三次握手四次挥手)

1.TCP协议和UDP协议的区别

  1. TCP基于有连接,UDP基于无连接。有连接就是TCP在传输前先发送连接请求和应答包,确定双方能正常传输后,才开始进行数据传输。无连接就是UDP在发送数据之前,并不考虑对方能否接收到,甚至目的地址可能都是无效。
  2. TCP能保证可靠传输,UDP不能保证可靠传输TCP。所谓可靠就是TCP能保证把数据一定送到目的地址。为了实现可靠,TCP采用有连接的,超时重传,应答机制等。而UDP则没有这些,也不能保证数据一定能送到。
  3. TCP结构复杂,消耗资源多,建立过程较慢复杂。UDP结构简单,消耗资源少,建立过程较快。
  4. TCP基于流模式,UDP是数据包模式。TCP把数据看成一连串无结构的字节流,没有边界,一段段传输构成了整个数据块。通过发送缓冲区和接受缓冲区来储存数据流。而UDP数据包模式,每一个数据报都是一个独立的对象,有着指定的大小。
  5. TCP连接只能是点到点,而UDP可以一对一,一对多或者多对多。TCP只能是点到点原因很简单,因为TCP的传输先要建立连接。因此,广播和多播只能采用UDP数据报的方式。
  6. TCP有确认,重传,拥塞控制机制,UDP在没有建立连接或者对方已经退出的情况下任然会继续发送数据,导致通信流量的浪费。

用途

TCP

用于实现可靠传输的情况,文件非常重要,对网络拥堵有较高要求的情况。

UDP

  1. 用于高速传输和实时性较高的场合(即使通信)。对于采用UDP的实时视频通信,如果出现丢包也只会出现短暂卡顿,但是如果采用TCP丢包后需要重发,会导致很长时间的卡顿。
  2. 包总量比较少的通信(DNS),客户端较多。
  3. 广播通信。

TCP粘包问题

TCP是字节流传输,是流模式,所以不存在粘包问题,问题主要出来应用层程序员没有根据自定义的协议合理切割数据包。

2.TCP三次握手与四次挥手

TCP的连接与断开

在这里插入图片描述
TCP/IP状态转换图
在这里插入图片描述

三次握手的过程:

刚开始客户端处于 Closed 的状态,服务端处于 Listen 状态。

第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN(c)。此时客户端处于 SYN_Send 状态。

第二次握手:服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,并且也是指定了自己的初始化序列号 ISN(s)。
同时会把客户端的 ISN + 1 作为 ACK 的值,表示自己已经收到了客户端的 SYN,此时服务器处于 SYN_REVD 的状态。

第三次握手:客户端收到 SYN 报文之后,会发送一个 ACK 报文,当然,也是一样把服务器的 ISN + 1 作为 ACK 的值,表示已经收到了服务端的 SYN 报文,此时客户端处于 establised 状态。

服务器收到 ACK 报文之后,也处于 establised 状态,此时,双方已建立起了链接。

为什么需要三次握手,而两次不可以

  • 第一次握手:客户端发送网络包,服务端收到了。
    这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
  • 第二次握手:服务端发包,客户端收到了。
    这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。
  • 第三次握手:客户端发包,服务端收到了。
    这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。
    因此,需要三次握手才能确认双方的接收与发送能力是否正常。

第二种解释

如果仅两次连接可能出现一种情况:客户端发送完连接报文(第一次握手)后由于网络不好,延时很久后报文到达服务端,服务端接收到报文后向客户端发起连接(第二次握手)。此时客户端会认定此报文为失效报文,但在两次握手情况下服务端会认为已经建立起了连接,服务端会一直等待客户端发送数据,但因为客户端会认为服务端第二次握手的回复是对失效请求的回复,不会去处理。这就造成了服务端一直等待客户端数据的情况,浪费资源。

三次握手的作用

确认双方的接受能力、发送能力是否正常。

指定自己的初始化序列号,为后面的可靠传送做准备。

如果是 HTTPS 协议的话,三次握手这个过程,还会进行数字证书的验证以及加密密钥的生成。

ISN是固定的吗?

三次握手的一个重要功能是客户端和服务端交换 ISN(Initial Sequence Number),以便让对方知道接下来接收数据的时候如何按序列号组装数据。
如果 ISN 是固定的,攻击者很容易猜出后续的确认号,因此 ISN 是动态生成的。

什么是半连接队列?

服务器第一次收到客户端的 SYN 之后,就会处于 SYN_RCVD 状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。

当然还有一个全连接队列,就是已经完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象。

SYN-ACK重传次数

服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传。

如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。

注意,每次重传等待的时间不一定相同,一般会是指数增长,例如间隔时间为 1s,2s,4s,8s…

三次握手的过程中可以携带数据吗?

第三次握手是可以携带数据的。

为什么第一第二次不可以呢?

假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据。

因为攻击者根本就不理服务器的接收、发送能力是否正常,然后疯狂着重复发 SYN 报文的话,这会让服务器花费很多时间、内存空间来接收这些报文。

也就是说,第一次握手可以放数据的话,其中一个简单的原因就是会让服务器更加容易受到攻击了。

而对于第三次的话,此时客户端已经处于 established 状态,也就是说,对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据页没啥毛病。

三次握手中第三次握手ACK丢失怎么办?

讨论见此

四次挥手的过程

刚开始双方都处于 establised 状态,假如是客户端先发起关闭请求,则:
第一次挥手:客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于 FIN_WAIT1 状态。
第二次握手:服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 +1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT 状态。
第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 的状态。
第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 +1 作为自己 ACK 报文的序列号值,此时客户端处于 TIME_WAIT 状态。
需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态
服务端收到 ACK 报文之后,就处于关闭连接了,处于 CLOSED 状态。

这里特别需要注意的就是 TIME_WAIT 这个状态了,这个是面试的高频考点,就是要理解,为什么客户端发送 ACK 之后不直接关闭,而是要等一阵子才关闭。

这其中的原因就是,要确保服务器是否已经收到了我们的 ACK 报文,如果没有收到的话,服务器会重新发 FIN 报文给客户端,客户端再次收到 ACK 报文之后,就知道之前的 ACK 报文丢失了,然后再次发送 ACK 报文。

还有一个原因是,如果没有TIME_WAIT这个端口立即又跟其他主机连接,这时旧的连接的报文被接受到,然而主机并不知道这是旧连接发送的报文,就会造成错误。

至于 TIME_WAIT 持续的时间至少是一个报文的来回时间。一般会设置一个计时,如果过了这个计时没有再次收到 FIN 报文,则代表对方成功,就是 ACK 报文,此时处于 CLOSED 状态。

实际上,现在的 Linux 提供了一种 方法,它可能通过给 socket 指定选项 SO_REUSEADDR 允许端口重用。

为什么是四次挥手

这取决于TCP关闭的特点,基于双全工的特性,TCP连接的任意一端都能够独立的关闭连接,也就是半关闭。
client先发送FIN告知对方我已经完成数据发送了,server回复ack来确定我知道了。这样一个流程,就关闭了client的发送信息通道。但是还可以接收来自server方的数据。
server此时已经知道接收不到client的数据了,但是还可以给它发送数据。如果server也没有啥数据要发送给对方了,server也会以FIN标志位发送一个信息给client,client接到后,也会传递一个ack表示知道了。这样子,双方都完成了关闭。

在Linux socket中
https://www.cnblogs.com/kex1n/p/7146054.html

发布了18 篇原创文章 · 获赞 0 · 访问量 291

猜你喜欢

转载自blog.csdn.net/weixin_42162340/article/details/103291292