1 预备知识
要了解TCP通信,必须得对TCP报文格式熟悉,下图是TCP报文格式,简单说下跟TCP连接三次握手和TCP断开三次握手及半关闭的四向握手有关的几个字段,
分别是:SYN、ACK、FIN以及序号和确认号字段。
以下假设客户端A想跟服务器B通信
2 TCP连接三次握手
三次握手(Three-way Handshake)其实就是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备。实质上其实就是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号,交换TCP窗口大小信息。
step1 A发出一个TCP报文,其中置SYN=1,并随机初始化一个数给序号字段,假设是seq=x;
step2 B收到请求后回复一个报文,置SYN=1,ACK=1,确认号为ack=x+1,序号也是一个随机值,假设为seq=y;
step3 A收到报文后回复B,置ACK=1,序号仍为x,确认号为y+1.
3 TCP关闭的四次握手
step1 A发出一个TCP报文,置FIN=1,假设此时的序号为x,确认号为y;
step2 B回复A,置ACK=1,序号为y-1,确认号为x+1;
...(B给A发数据阶段)
step3 B发出报文给A,置FIN=1,序号假设为z,确认号为x+1;
step4 A回复B,置ACK=1,序号为x,确认号为z+1
4 问题
1、TCP连接时最后一次握手可以省略吗?
反例:如客户端发出连接请求,但因连接请求报文丢失而未收到确认,于是客户端再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接,客户端共发出了两个连接请求报文段,其中第一个丢失,第二个到达了服务端,但是第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到连接释放以后的某个时间才到达服务端,此时服务端误认为客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同意建立连接,不采用三次握手,只要服务端发出确认,就建立新的连接了,此时客户端忽略服务端发来的确认,也不发送数据,则服务端一致等待客户端发送数据,浪费资源。
2、什么是半连接队列?
服务器第一次收到客户端的 SYN 之后,就会处于 SYN_RCVD 状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。
全连接队列,就是已经完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象
3、三次握手过程中可以携带数据吗?
其实第三次握手的时候,是可以携带数据的。但是,第一次、第二次握手不可以携带数据
为什么这样呢?大家可以想一个问题,假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据。因为攻击者根本就不理服务器的接收、发送能力是否正常,然后疯狂着重复发 SYN 报文的话,这会让服务器花费很多时间、内存空间来接收这些报文。
也就是说,第一次握手不可以放数据,其中一个简单的原因就是会让服务器更加容易受到攻击了。而对于第三次的话,此时客户端已经处于 ESTABLISHED 状态。对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据也没啥毛病。
4、SYN攻击是什么?如何防范
SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复确认包,并等待Client确认,由于源地址不存在,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。
常见的防御 SYN 攻击的方法有如下几种:
缩短超时(SYN Timeout)时间
增加最大半连接数
过滤网关防护
SYN cookies技术
5、挥手为什么需要四次?
因为当服务端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当服务端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉客户端,“你发的FIN报文我收到了”。只有等到我服务端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四次挥手。
6、四次挥手释放连接时,等待2MSL的意义?
为了保证客户端发送的最后一个ACK报文段能够到达服务器。因为这个ACK有可能丢失,从而导致处在LAST-ACK状态的服务器收不到对FIN-ACK的确认报文。服务器会超时重传这个FIN-ACK,接着客户端再重传一次确认,重新启动时间等待计时器。最后客户端和服务器都能正常的关闭。假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。
其他
- 关于 OPTIONS 请求
作用:获取服务器支持的HTTP请求方法 & 用来检查服务器的性能
当发生接口跨域时,非简单请求会发生 OPTIONS 请求。简单请求一般满足两个条件
1、请求方法为 GET,POST,HEAD
2、请求头仅限于以下几类:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
不满足这两个条件的都叫非简单请求。所以对于 delete,put 请求一定会发生 OPTIONS 请求,对于请求类型为 application/json 也会发生 OPTIOINS 请求
和跨域有关的请求头:
Access-Control-Allow-Origin,Access-Control-Allow-Credentials(是否需要cookie),Access-Control-Allow-Headers