[计算机网络] tcp建立连接(三次握手)
0.补充
tcp连接是通过客户端合服务端的socket交互完成,完成后建立一个连接(相关信息应该是操作系统负责维护)
连接由四元组进行唯一标识(源地址、源端口、目的地址、目的端口),并且当线程结束关闭socket后其创建的连接仍然可以使用。
1.三次握手
1)客户端发送SYN=1,SEQ=J。 【状态变为SYN_SENT】
2)服务端接收后,发送SYN=1,ACK=J+1,SEQ=K。 【状态变为SYN_RCVD】
3)客户端接收后,发送ACK=K+1,SEQ=J+1。完成后客户端的socket的connect函数返回(此时客户端socket认为已经完成连接)【状态变为ESTABLISHED】
4)服务端接收后,客户端认为已完成连接。【状态变为ESTABLISHED】
2.补充:
1)初始化过程
客户端是创建socket并绑定属性,然后调用connect函数主动连接服务器
客户端则是创建socket并绑定属性,然后调用bind绑定端口,调用listen注册网络端口监听服务。
2)第一次握手
服务端接受到客户端的SYN。
a.若半连接队列未满,则将该连接状态变为SYN_RCVD,然后将连接信息放到便链接队列中。
b.若半连接队列已满,则不会更改连接状态,而是会丢弃该连接。
因此一种攻击方式是SYN Flood,使得服务器的半连接队列无剩余空间,从而无法与正常请求建立连接。
紧急应对方法是:将配置中的suncookies值修改为1,这会使得socket无视队列最大值进行连接处理。
SYN Flood分为两种,第一种是发送SYN后不回应服务器的ACK,第二种是回复一个虚假IP的ACK,使得服务器错误发送ACK+SYN。
3)第二次握手
客户端收到SYN+ACK后,连接状态概为ESTABLISHED。
在网络编程时,也就是connect函数返回。
4)第三次握手
全连接队列最大值一般是128。
服务器接收到客户端的ACK。
a.若全连接队列未满,将该连接状态从SYN_RCVD变为ESTABLISHED。随后服务器将该连接从半连接队列中移除,并将连接的信息放到全连接队列中。
b.若全连接队列已满,则不会立即更改连接状态。会根据tcp_abort_on_overflow的值来进行处理。
若值为0,则进行二进制指数退让,给客户端定时从新发送SYN+ACK来从新握手。
若值为1,则重置连接(发送RST给客户端)
3.为何是三次握手而不是两次握手?
方位已失效的连接请求报文传送过来产生错误。
考虑这样的情况:
client发送SYN报文后,该报文在网络某一个节点被滞留。
client认为报文丢失后重新发送SYN报文,这次正常建立了连接,完成数据交互后正常关闭了连接。
此时最早的报文才到达server,后者从新建立连接。
若采用两次握手,会导致server认为建立了连接,但是client却没有,进而导致一系列不必要的开销。