为什么要3次握手?假设存在以下过程:
A->B (写信,我想和你吃饭)B->A (写信,收到,我也想和你吃饭)A->B (写信,收到)
其实呢,最开始两步,是因为通信的双方要互相通知对方自己的初始化的Sequence Number(缩写为ISN:Inital Sequence Number)——所以叫SYN。
引申的问题有以下三个:
1、为什么不是四次握手?”收到,我也想和你吃饭“为什么不分成2次信发送? 答案:这个是为了节省网络的传输,类似tcp的延迟确认原理一样~~~~
2、为什么不是两次握手? 答案:那么,如果B给A写的 "收到,我也想和你吃饭" 信半路在路上丢了,那么可能造成A不知道B愿不愿意陪A吃饭。这时候A会认为B还没回答,一直在等回答B回答。。。。 在计算机中,表现为B给A发的数据包全部都被A丢弃了,因为A认为链接还没建立成功。而B看到给A发的数据包一直没有回应,那么B不断重试,不断给A发。。。。。
3、如果在B->A(写信,收到,我也想和你吃饭)之后,A就断线了。那么B怎么呢? 答案:B每隔一段时间就给A重新发短信~~默认重发5次,5次的重试时间间隔为1s, 2s, 4s, 8s, 16s。共等待1s + 2s + 4s+ 8s+ 16s + 32s = 2^6 -1 = 63s后,然后断开念头。 问题3,又可以这样问,建连接时,如果SYN超时,那么会怎么样? 答案:在计算机中表现如果客户端发完SYN后就马上断线,那么服务器将会等待63秒,重发5次SYN-ACK,如果仍然无果,那么TCP才会把断开这个连接。
4、世界总是充满了恶意,假设存在大量的类似A这样的人,不断给B (写信,我想和你吃饭)。。。。那么B肯定得累死,这就是大名鼎鼎的SYN洪水攻击。 解决:因此linux给了个参数tcp_syncookies来专门处理这种情况。这种情况原理是这样的,A不会再苦苦等B 63秒,而是给B发一个特殊的暗号(Cookie)。然后B如果收到了还是想建立连接,那么就使用这个特别的暗号Cookie来建立连接即可。【当SYN队列满了后,,,】 解决方案存在的问题:这种情况【千万不能应用于正常的大负载的连接的情况】,因为可能服务器给客户端发的Cookie客户端会真的没收到。。。。这时候就gg了。参数可供你选择, 第一个是:tcp_synack_retries 可以用他来减少重试次数; 第二个是:tcp_max_syn_backlog,可以增大SYN连接数; 第三个是:tcp_abort_on_overflow 处理不过来干脆就直接拒绝连接了
参考https://blog.csdn.net/cws1214/article/details/52430554
为什么要4次挥手?
理论上完全可以做到3次挥手。Server完全可以同时发送FIN和ACK,即将一般情况下的步骤2和步骤3合并!这就是延迟确认优化,在RFC793 3.5节! 而存在则合理,为什么TCP搞成了4次挥手呢?是因为Server在收到Client的FIN报文后会立即ACK,然后再通知应用层来决定Server端到Client端的单向连接是否要关闭,如果应用层没数据要发则Server此时再发一个FIN,这就导致比TCP建立多了一步,因为FIN和ACK不是在同一报文中发送。