一、TCP协议简介
TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议
一般问到TCP协议的时候 最常见的是TCP连接建立和断开的过程,也就是三次握手和四次挥手
Tcp报文格式
ACK:确认序号有效。
RST:重置连接。
SYN:发起一个新连接。
FIN:释放一个连接。
1.1 三次握手
(1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
(2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
(3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
SYN Flood 攻击原理
SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址是不存在的,因此,Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。
1.2 四次挥手
(1) 第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
(2) 第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
(3) 第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
(4) 第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手,而client进入TIME_WAIT状态。
上面是一方主动关闭,另一方被动关闭的情况,实际中还会出现同时发起主动关闭的情况,具体流程如下图:
为什么建立连接是三次握手,而关闭连接却是四次挥手呢?
三次握手:两次握手可能因为丢包而出现死锁,假设在两次握手场景中,C向S发送请求,S收到并发送确认请求给C,这时候S认为连接已经建立,并开始发送数据给C,但是那个确认请求丢包了,C不认为请求建立了,C当然会拒绝接受S发送来的数据,并且再去请求连接。S在发出的数据超时后,重复发送同样的数据。这样就形成了死锁。最后回答握手当然可以四次五次一直握下去,但三次已经够了。
四次挥手:关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
TCP和UDP的区别
TCP提供的是面向连接的、可靠的数据流传输,而UDP提供的是非面向连接的、不可靠的数据流传输。简单的说,TCP注重数据安全,而UDP数据传输快点,但安全性一
设置TIME_WAIT的原因
1可靠地实现TCP全双工连接的终止
TCP协议在关闭连接的四次握手过程中,最终的ACK是由主动关闭连接的一端(后面统称A端)发出的,如果这个ACK丢失,对方(后面统称B端)将重发出最终的FIN,因此A端必须维护状态信息(TIME_WAIT)允许它重发最终的ACK。如果A端不维持TIME_WAIT状态,而是处于CLOSED 状态,那么A端将响应RST分节,B端收到后将此分节解释成一个错误
2允许老的重复分节在网络中消逝
在关闭“前一个连接”之后,马上又重新建立起一个相同的IP和端口之间的“新连接”,“前一个连接”的迷途重复分组在“前一个连接”终止后到达,而被“新连接”收到了。为了避免这个情况,TCP协议不允许处于TIME_WAIT状态的连接启动一个新的可用连接,因为TIME_WAIT状态持续2MSL(最大报文段生存时间),就可以保证当成功建立一个新TCP连接的时候,来自旧连接重复分组已经在网络中消逝。
大量 TIME_WAIT 产生的原因及解决办法
原因:对于基于TCP的HTTP协议,关闭TCP连接的是Server端,这样,Server端会进入TIME_WAIT状态,可想而知,对于访问量大的Web Server,会存在大量的TIME_WAIT状态。
解决办法:
1开启socket重用,允许将TIME_WAIT的socket重新用于TCP连接
2开启快速回收。
大量CLOSE_WAIT产生的原因及解决办法
主要原因是某种情况下对方关闭了socket链接,但是我方忙与读或者写,没有关闭连接。或者程序压根就忘记了这个时候需要关闭连接,于是这个资源就一直被程序占着。
解决办法:
具体问题具体解决,总结一句话就是在处理资源时一定要记住自己申请的资源要记得主动释放。