经过腾讯的六次技术面的考验,每次基本必问TCP的一些知识。因此,笔者一直都想总结一下,但由于太忙(懒),一直没有去做,趁这会儿有时间,特在此处总结下,希望对大家有帮助。
众所周知,TCP是面向连接的协议,此处的“连接”,只是抽象的连接,即,服务端和客户端进行指定端口的数据传输,由于TCP协议是对端传送数据的,所以,两端在通讯时,就相当于通过抽象的信道,将两个端口进行连接,从而形成抽象的“连接”。
具体数据传输过程如下图所示:
而对于连接的建立和拆除,则分别需要三次和四次。若这部分不太清楚可以参考一下我之前的文章:TCP三次握手和四次挥手详解,这里我就不再赘述了。
为了叙述和读者理解方便,此处贴一张图:
经过上面繁杂的介绍,那么我们来一步步分析一下“三次握手”的过程:
1、服务端处于LISTEN状态,客户端处于CLOSED状态;
2、客户端打开,并进行SYN的发送,处于SYN_SENT状态;
3、服务端收到此条消息后,转为SYN_RCVD状态,并对客户端进行消息回复;
4、客户端收到此条消息后,转为ESTABLISHED状态,并发送一个ACK的确认消息。
5、服务端收到此条消息后,转为ESTABLISHED状态。
至此,三次握手完成。
然而,聪明的你,通过上面的分析,你可能会得到这样的结论:accept()发生在第3步,原因是,此时accept()函数需要给此次连接分配资源。的确,最初是想这样设计的。但是,设想一个情景,若有10000个客户端都和该服务端进行连接,发送SYN,服务端收到之后,这些客户端却不再理会服务端的回复,然而此时服务端的资源却都用accept()分配了。这就是所谓的“DDOS攻击”。
为了解决这个问题,accept()于是被放在三次握手之后。
当然,这样也不能保证不能被攻击,当然这是后话。