TCP
为什么需要三次握手
通俗一点来讲:
第一次握手是验证客户端可以正常发送信息
第二次握手是验证服务器端可以发送信息
第三次是客户端向服务器发送信息,确保双方可以正常通讯
目前是为了确定双方可以正常的接收信息和发送信息,避免其中一方出现了问题
其实不止是为了确定双方是否可以正常通讯
还可以利用数据包的选项来传输特殊信息,交换初始序列号ISN
- 客户端发送一个SYN(SYN=1),和seq指定客户端的初始序列号seq=x(此时客户端处于synSend状态)
- 服务器端在接收到SYN之后,也发送一个自己SYN(SYN=1),并指定一个自己的初始序列号seq=y,同时会将客户端的SYN+1作为ACK回传,表示已经收到客户端的信息了(服务器进入synReced)
- 客户端收到服务器响应的SYN后,把服务器的SYN码+1作为ACK和seq=x+1回传给服务器端,表示收到服务器的SYN了,期望下一次收到的数据是seq=y+1
- 当服务器接收了ACK之后,双方都进入established状态,创建TCP链接
ISN是固定的么
ISN是客户端和服务器端交互数据比较重要的功能之一,用户让对方知道接下来要接收数据时如何按序列号组织数据
ISN不是固定的,是自动选择的,每个连接都有不同的ISN
如果是固定的值,很容易被攻击者猜出来后续的确认码
确定双方的是ACK码
为什么握手不能是两次
如果只有两次握手,只能确定客户端有发送能力,服务器则有接收能力
需要有第三次握手,才能确保服务器端有发送能力和客户端有接收能力。
三次握手的时候可以携带数据吗
第1,2次绝不能携带数据,因为如果有人攻击服务器的话,服务器在接收数据的时候会花费更多时间来接收这些报文
第3次可以携带数据,因为双方都确定了发送、接收能力
洪泛攻击
SYN攻击指的是客户端在短时间内,伪造大量不存在的IP地址,向服务器发送SYN包
服务器收到之后,会回复确认包并等待客户端响应,但由于IP是不存在的,服务器会进行重发直到超时
这些伪造的SYN包会占用半连接队列,导致正常的SYN请求因为队列满而被移除,导致网络堵塞,系统瘫痪
为什么需要四次挥手
因为TCP都是双向(一发一收)的,必须通过四次数据传输才能让双方完全停止数据发送。
四次挥手过程如下
- 客户端发送一个FIN=1和seq=u字段,告诉服务器说我要结束发送请求了
- 服务器接收到数据之后,发送FIN=1,ack=u+1,seq=v,发送之后服务器进入close_wait状态,客户端进入fin_wait2状态
- 服务器发送fin=1,ack=u+1,seq=w后,进入last_ack状态,等待客户端最后一个ACK
- 客户端接收到请求之后,发送seq=u+1,ack=w+1并进入time_wait状态,在这个状态期间内(2MSL),如果没有接收到服务器的ACK才真正关闭连接,服务器在接收到包后进入closed状态,客户端也进入close状态
TIME-WAIT
全称,2Maximum Segment Lifetime,意思是两个最大段生命周期
1个 MSL 保证四次挥手中主动关闭方最后的 ACK 报文能最终到达对端
1个 MSL 保证对端没有收到 ACK 那么进行重传的 FIN 报文能够到达
TCP是如何保证可靠性的
- TCP连接会经过三次握手和断开前进行四次挥手,确保了连接和端口的可靠性
- 检验和:TCP会校验数据是否有差错和一次,如果有差错和异常会丢弃TCP端重新发送,在校验和时,会在TCP首部家上12字节的伪首部,分为三个部分:TCP首部,数据,伪首部
- 序列号,在发送数据端和接收数据端时都会有个应答包(ACK),如果没有回应,还会有重发机制,确保数据完整性
- 超时重传,指的是发出去的数据包和接收包之间的时间,如果超出了,这个时候就被认为丢包,需要重新发送 (如果重发多次也没有收到对端的包,就会被认为接收端有异常,强制关闭端口)
- 滑窗窗口控制,弥补超时重传机制效率低,因为发送一个包到发送下一个包需要花费一段时间,滑窗窗口控制指的是不用等这次包发送完毕后等接收包,才能继续发送下一个包
- 快速重传,不以时间为驱动,而是以数据驱动重传