不同的地方在于:
建立连接时,由于服务器没什么其他的事做,基本是同步的,所以服务器发送ack的时候,会顺带发送syn
因此连接是这样的:
(1)c----->syn---->s
(2)c<-----syn_ack<----s
(3)c----->ack---->s
而释放连接时,由于双方的动作不一定同步,比如一方要关闭,但另一方的数据还没传结束呢,所以往往上面的(2)步往往不能一起做完了,而是拆分成两步,先ack一下,表示知道您要关闭了,我这边稍等下再fin,所以关闭连接往往是这样的:
(1)c----->fin---->s
(2)c<-----ack<----s
(3)c<-----fin<----s
(3)c----->ack---->s
当然,首先接到fin的一方如果没什么数据要传了,也是可以三步搞定的,完全看协议栈的具体实现:
(1)c----->fin---->s
(2)c<-----fin_ack<----s
(3)c----->ack---->s一次完整的TCP通信过程需哪几个阶段?
正确答案:(1)连接建立:需要经过“三次握手”;(2)报文传输:当客户进程与服务器进程之间的TCP传输连接建立之后,客户端的应用进程与服务器端的应用进程就可以使用这个连接,进行全双工的字节流传输;(3)连接释放:连接的释放过程很复杂,客户端与服务器端都可以主动提出释放连接请求;客户端主动提出请求的连接释放需要有“四次握手”的过程。如果是同步套接字的时候。你可以在发送(或接收)后向主线程发送一个消息,通知现在套接字可用。或者专门设定一个标志位,比如int flag;0是空闲,1是正在发送,-1是正在接收。每次进行套接字 *** 作前先设置标志, *** 作完成后释放标志。
如果是异步套接字,只要判断该套接字是否刻度可写可以参考
>A向B发送SYN
B向A发送SYN+ACK
A向B发送ACK,链接建立
A向B发送FIN
B向A发送FIN+ACK
A向B发送ACK
B向A发送ACK链接断开
为了更好的理解TCP建立连接与释放连接的过程,我们不妨先了解TCP报文结构。
TCP报文包含 首部 和 数据部分 :
重点认识一下 TCP首部 结构:
1、源端口与目的端口:
各占两个字节,共4个字节。用来告知主机该报文的源与目的。
2、序号(seq number)
由于TCP是面向流的有序可靠连接,在一个TCP连接中传输的字节流中的每个字节都需要按顺序编号。
序号字段指的是本报文段所发送的数据的 第一个字节 的序号。
3、确认号(ack number)
表示 期望收到对方下一个报文段的序号值 ,同时表示前面的序号值都已经 成功接收 ,体现 累积确认机制 。
4、确认ACK
当ACK=1时,确认号有效。
5、同步SYN
当SYN=1时,表明这是一个请求连接报文段。
6、终止FIN
当FIN=1时,表示此报文段的发送方的数据已发送完毕,要求释放TCP连接。
7、 窗口大小(window size)
流量控制 中的滑动窗口大小,根据接收方的接收缓冲区剩余大小设置。
TCP 的整个交流过程可以总结为:建立连接,传输数据,释放连接。
TCP连接的建立采用客户端-服务器模式,我们将主动方成为客户端(Client),被动方成为服务器(Server)。
1、 第一次握手 :Client主动打开连接,发送TCP报文( SYN = 1,seq = i ),进行第一次握手,进入 SYN_SEND 状态;
2、 第二次握手 : Server收到了SYN报文,发送返回报文( ACK = 1,SYN = 1,ack = i+1, seq = j ),进行第二次握手,进入 SYN_RCVD 状态;
3、 第三次握手 : Client收到来自Server的报文,返回ACK报文( ACK = 1, ack = j+1,seq = i+1 ),进行第三次握手,进入 ESTABLISHED 状态; 另外, 第三次握手一般已经可以携带数据了 。
TCP有一个特别的概念叫做 半关闭 ,这个概念是说,TCP连接时全双工的连接,因此在关闭连接的时候,必须关闭传送和接收两个方向上的连接。
1、 第一次挥手 : Client发送关闭连接报文段( FIN= 1, seq = n ),进入 FIN_WAIT_1 状态;
2、 第二次挥手 : Server收到来自Client的FIN之后,立即返回一个 ACK=1 报文段(ack = n+1),进入 CLOSE_WAIT 状态;
此时Server还是可以发送数据给Client。
3、 第三次挥手 : 当Server确定所有数据都发送完毕之后,发送 FIN=1 报文段(seq = m),进入 LAST_ACK 状态;
4、 第四次挥手 : Client收到之后,返回 ACK=1 报文段(ack = m+1),进入 TIME_WAIT 状态;
Client等待2MSL(MSL,最长报文段寿命)之后进入CLOSED状态,Server收到最后一个ACK之后,也进入CLOSED状态。
在三次握手过程中,Server发送第二次握手报文之后,收到Client的ACk之前的状态称为 半连接 状态。在半连接状态的Server会为其认为即将完成连接的Client分配资源。
而SYN Flood攻击就是,在短时间内伪造大量不存在的IP地址,向Server不断发送SYN包,Server为这些伪造的Client分配资源,并返回SYN+ACK报文段,由于IP地址无效,所以Server不会收到第三次握手的ACK,需要不断发送直至超时,这些伪造的Client长时间占用未连接队列与Server预分配的资源,造成Server崩溃,无法响应正常的SYN包。
1、SYN cookies技术:先不分配数据区,而根据SYN计算一个cookies值,当收到Client的ACk之后,再进行对比,分配资源。
2、增大最大半连接和缩短超时时间。
1、TIME_WAIT状态能确保Server正常进入CLOSE状态:
TIME_WAIT状态是在Client发完最后一个ACK之后进入的状态,如果这个ACK丢失,则Server不能确认进入CLOSE状态,超时后,Server会重新发送FIN报文段,此时处于TIME_WAIT状态的Client就能收到FIN,重发ACK,确保四次挥手完成。
2、TIME_WAIT状态有 净空 的效果:
防止已经失效的连接请求出现在下次连接中。经过TIME_WAIT状态,可以使本连接内的所有请求都在网络中消失(从而起到净空的效果,不会赢下下一次连接)。
1、 只有主动close一方才会出现TIME_WAIT状态,只有TCP连接为 短连接 情况下才有可能出现大龄的TIME_WAIT状态。
2、 服务器使用短连接,每次客户端请求后,服务器都会主动发送FIN关闭连接。最后进入TIME_WAIT状态。由此,如果访问量过大的Web Server,会存在大量的TIME_WAIT状态。
可以通过修改内核参数,快速回收TIME_WAIT资源。
3、如果一直存在大量TIME_WAIT状态,回收不及时的话,会占用大量服务器资源,可能造成该无法提供服务的问题。
参考
[1] 理解TCP 和 UDP
[2] 《计算机网络》
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)