TCP 握手挥手面试常见问题

概述:虽然IP层将分组数据送到目的主机,但严格讲,计算机网络中的两个主机通信其实是两个主机上的应用进程通信,通信的端点不是主机而是主机上的应用进程。网络层提供主机间的逻辑通信,运输层提供端口间的逻辑通信。


UDP的主要特点:
1、UDP是面向无连接的运输层协议,发送数据前不用建立连接,可靠性降低但提高效率
2、UDP是提供最大努力的交付服务
3、UDP是面向报文的,即一次发送一个报文,不合并、不拆分,但如果数据过长会在网络层IP分片传输,影响网络层效率
4、UDP无法避免网路拥塞时的数据丢失,但保证了发送数据的稳定速率
5、UDP支持一对一、一对多、多对多的通信
6、 UDP首部较短只有8字节,较TCP的20字节(只包括固定字段长度) 减小了开销。
UDP首部字段:
1、源端口
2、目的端口
3、长度,数据报的长度
4、校验和,验证传输信息是否有错,有错就丢弃

问题:QQ 为什么以 UDP 协议为主,以 TCP 协议为辅?,但并不能说QQ的通信是不安全的,

最本质上UDP的优势还是带宽的利用。这一切要回归到99~03年的网络状况,当时网络的特点就是接入带宽很窄而且抖动特别厉害。当时没有epoll这种可以支持成千上万tcp并发连接的技术。当网络差到一定程度了,TCP的优势反而会成为劣势。即时通讯时效性要求高,用TCP维持多人同时在线是个问题[1], 涉及到服务器数量,系统调优,编程手段等很多方面。比如在使用QQ进行文件传输等活动的时候,就会使用TCP作为可靠传输的保证。

TCP的主要特点:
1、TCP是面向连接的运输层协议。使用TCP之前必须建立TCP连接,就跟打电话一样,接通后才能通话
2、TCP连接是点对点的,只能有两个端口
3、TCP提供可靠的服务,无差错、不丢失、不重复、按序到达,而运输层以下都是不可靠的尽力提供最大努力的服务。
4、TCP提供全双工通信,通信两端都设有发送缓存与接收缓存,可在空闲时发送或接受
5、TCP面向字节流
套接字(Socket)= IP地址:端口号

TCP报文首部字段:

主要首部字段解释:
1、序号:该报文段的数据段第一个字节占整条报文数据段的位置
2、确认号:期望收到的下一个报文段的序号(如:上一个报文段序号位600,数据段长度为100,在正确接收后,这次期望接受的数据序号为700)
3、窗口大小:指出允许对方发送的数据量,可动态变化
4、校验和:验证数据完整性与正确性
5、紧急指针:指出本报文字段中紧急数据的尾部位置,注意:当窗口为0时也可以发送紧急数据
6个控制位解释:
1、ACK起应答作用,占1位;仅当ACK=1时,确认号字段才有效,ACK=0时,确认号无效
2、 SYN起同步作用; 当SYN=1,ACK=0时表示:这是一个连接请求报文段。 若同意连接,则在响应报文段中使得SYN=1,ACK=1。因此,SYN=1表示这是一个连接请求,或连接接受报文
3、FIN 用来释放一个连接;FIN=1表示:此报文段的发送方的数据已经发送完毕,并要求释放TCP连接
4、PSH 表示接收方应将报文交给应用层
5、RST 表示连接重置
6、URG 表示紧急指针,URG=1表示有紧急数据
TCP可靠传输机制
1、流量控制,滑动窗口机制——让发送方发送速率不太快,接收方来得及接收,通过滑动窗口机制实现,即接受方多次发出响应报文修改首部字段的窗口值以控制发送方数据发送速率
2、拥塞控制,慢开始、拥塞避免、快重传、快恢复机制

SYN攻击原理:

在三次握手过程中,Server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接(half-open connect),此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址是不存在的,因此,Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。SYN攻击是一种典型的DDOS攻击,检测SYN攻击的方式非常简单,即当Server上有大量半连接状态且源IP地址是随机时,则可以断定遭到SYN攻击了,使用如下命令可以让之现形:

几种状态【每个都很重要】

CLOSED: 这个没什么好说的了,表示初始状态。

LISTEN: 这个也是非常容易理解的一个状态,表示服务器端的某个SOCKET处于监听状态,可以接受连接了。

SYN_SENT: 这个状态与SYN_RCVD遥想呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。

SYN_RCVD: 这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本上用netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。

ESTABLISHED:这个容易理解了,表示连接已经建立了。

FIN_WAIT_1: 这个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。
FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。
TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文(第四次挥手就不要FIN了),就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。

CLOSING: 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。

LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。

Time_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接

1、 为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?

这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。

2、 为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?

这是因为:虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。

TCP在传输之前会进行三次沟通,一般称为“三次握手”,传完数据断开的时候要进行四次沟通,一般称为“四次挥手”。

两个序号和三个标志位:

  (1)序号:seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
  (2)确认序号:ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,ack=seq+1。
  (3)标志位:共6个,即URG、ACK、PSH、RST、SYNFIN等,具体含义如下:
  (A)URG:紧急指针(urgent pointer)有效。
  (B)ACK:确认序号有效。
  (C)PSH:接收方应该尽快将这个报文交给应用层。
  (D)RST:重置连接。
  (E)SYN:发起一个新连接。
  (F)FIN:释放一个连接。





猜你喜欢

转载自blog.csdn.net/qq_33608638/article/details/79911026