Chinaunix

标题: TCP/IP三次握手讨论 [打印本页]

作者: kkshaq    时间: 2015-06-04 20:31
标题: TCP/IP三次握手讨论
TCP/IP 连接采用三次握手,用来建立可靠的连接

对于为什么需要采用三次握手的原因:

谢希仁版本的注解是:







他认为,当socket close之后,收到SYN+ack报文之后,会不理睬并抛弃报文。导致另外一边白白等待。。


但是socket close之后,如果再收到报文,不是应该返回RST报文吗??另一端收到rst报文之后可以根据这个报文,判断是否连接成立,
所以谢的理由 这里是不是有问题?


有没有更好的三次握手原因解释
作者: wangspace    时间: 2015-06-04 21:18
理论结合实践,抓下包看看三次握手和四次挥手的过程:)
作者: kkshaq    时间: 2015-06-04 22:06
回复 2# wangspace

过程理解的,但是上面的这种情况怎么模拟??客服端迷失的连接报文,再次到达服务端,导致对方发送SYN+ACK,但是客户端已经close。此时客服端是回应rst吗?还是什么都不回应
   
作者: wangspace    时间: 2015-06-04 22:35
本帖最后由 wangspace 于 2015-06-04 22:40 编辑


http://www.cnblogs.com/yuilin/archive/2012/11/05/2755298.html
主要看下面的评论
作者: cokeboL    时间: 2015-06-05 09:05
任何一次确认都有可能丢失,不管设计多少次确认机制,最后一次确认都有可能丢失,所以握手就是个屁,只是在网络不好的状况下让人们看上去放心些。
常规的tcp通讯还不是要应用层自己做心跳
网络不够良好的情况下增加了保证了连接百分比,其实还是一坨,严密的逻辑都是要应用层根据实际需求辅以超时

然后,还浪费了很多流量,不过多数情况下这点流量不是瓶颈不引起注意

google不是在搞quic,想用udp替代tcp做http的载体吗?说明科学家们终于想通了
作者: cokeboL    时间: 2015-06-05 09:08
tcp需要连接,就两路握手就够了
断开也只要两次就足够了,对方都断开了,你还发,明显是错误逻辑,针对双工设计的断开四次也是屁
作者: cokeboL    时间: 2015-06-05 09:10
从connect到close,以及中间的通讯如果有请求应答式的,都需要应用层辅以超时机制,既然如此,传输层不如干脆就省去
浪费那体力号称保证了但未必,画蛇添足
作者: haokuankuan    时间: 2015-06-09 12:57
tcp三次握手采用的是三军问题模型,有兴趣的查看一下
作者: windoze    时间: 2015-06-11 14:26
其实没啥必要啊,本来一问一答两次就够了,问题是TCP发明那个年代网络可靠性太差,工程师们不放心就又加了一次,之所以没再加是因为大家其实心知肚明无论再加多少次其实都是一样的。
作者: cokeboL    时间: 2015-06-11 14:33
回复 9# windoze


      我自己在上面说的都是自以为,我都不敢确信,有猫大师偶像发话我就放心了!
作者: windoze    时间: 2015-06-11 15:52
回复 10# cokeboL

其实多级次握手也不是完全没用,比如SCTP用4次握手,连接状态在第二个来回才建立,这样可以防止SYN Flooding,因为你得很精确的连续两次伪造源地址发包才能骗过对方,基本上不可行,但像TCP这样的3次握手,既不够简洁又不够安全,还不如不用。
作者: kkshaq    时间: 2015-06-11 20:55
回复 9# windoze

最后一次的客服端的ack报文不是确认吗?怎么会没用啊?求解释清楚一点。只有收到ack应答,才说明服务器端的syn被客户端接受了啊。。。你为什么说无论多次此都没用呢?
我的理解是,客户端开始发送syn连接报文给服务器,服务器收到之后,发送ack+syn报文,然后等待客服端的ack报文,同时采用超时重传的机制。这样就可以防止最后的客服端的ack报文丢失啊。
求指教
作者: kkshaq    时间: 2015-06-11 20:58
回复 5# cokeboL

最后一次的ack确定报文丢失,服务器可以通过超时重传来解决啊。超过时间没有收到ack报文,服务器就重发syn连接报文给客服端,导致客服端重新发送ack报文。问题不就解决了吗?
   
作者: windoze    时间: 2015-06-11 22:12
本帖最后由 windoze 于 2015-06-11 22:17 编辑

回复 12# kkshaq

客户端只是发了一个ACK而已,它也不知道服务器端到底收到没有,想知道结果必需得让服务器端再发一个ACK过来。
同理服务器端也不知道自己再发的那个ACK客户端到底收到没有,想知到结果必需得让客户端再发一个ACK过来。
……
……
……
……
……
……
然而无论你重复多少次,都并没有什么卵用。


超时重传也不解决问题,因为有可能是对方的回复你没收到,甚至有可能无论你再催多少遍还是收不到。
不信?想象一下两边在用光纤通信,然后一方的激光二极管烧了……
作者: 蛮多肉    时间: 2015-06-12 06:16
在多数情况下2次握手够了

极端情况下,N次握手都不够

这个第三次握手

就如同 switch(){
      case:;
      default:
      break;
       }

是个逻辑握手!
作者: cokeboL    时间: 2015-06-12 08:57
回复 13# kkshaq


    任何一个包都可能丢,包括为了确认发的包,所以并没有什么卵用。透过现象看本质,直接抓住最根本的地方来想就清楚了
作者: zhaohongjian000    时间: 2015-06-12 09:34
楼上几个真能扯,本来不想回,越讨论越扯淡。

假设A向B发起连接,A到B是通的,B到A不通,两次握手的结果是B认为连接成功建立,而A知道连接不成功。
三次握手是让双方确认两边网络都通所需要的最少次数。少于三次,无法确认双方网络都通。

15楼举的例子,恰恰在反驳自己。单向通的网络会卡在前两次握手。如果第三次握手的包丢失,至少证明双方
网络都是通的,只是不稳定。这种情况可以用rst包重新建立连接来解决。

在两次握手就可以建立连接的情况下,意味着服务端收到一个包就要建立一个连接,DoS攻击真是轻松...
作者: windoze    时间: 2015-06-12 10:34
回复 17# zhaohongjian000

那你觉得现在3次握手服务器端是在收到了第几个包的时候建立链接?
作者: zhaohongjian000    时间: 2015-06-12 11:28
回复 18# windoze


    服务端收到第三个包进入ESTABLISHED状态,虽然因为收到第一个包进入SYNRECVD状态还是可以DoS,但是SYNRECVD状态可以加快回收。
数据开始传输后就不能随便回收了,所以一个包就进入ESTABLISHED状态,抗DoS能力只会更低。
作者: windoze    时间: 2015-06-12 13:56
回复 19# zhaohongjian000

刚才回的贴怎么不见了?重发一遍

服务器端虽然在收到第3个包的时候才将链接状态设置为ESTABLISHED,但在收到第一个SYN时就已经分配了链接相关资源,从防SYN flooding这一点而言三次两次没什么差别。
要想防SYN flooding,就得像SCTP那样,第二次收到客户端发来的COOKIE-ECHO包的时候才分配链接相关资源。
作者: kkshaq    时间: 2015-06-12 16:54
windoze 发表于 2015-06-11 22:12
回复 12# kkshaq

客户端只是发了一个ACK而已,它也不知道服务器端到底收到没有,想知道结果必需得让服务 ...


”客户端只是发了一个ACK而已,它也不知道服务器端到底收到没有,想知道结果必需得让服务器端再发一个ACK过来“,我觉得这句话有问题,客服端根本不需要等待服务器发来ack报文,因为此前他就认为已经建立了连接。



客户端首先发送syn报文给服务器,服务器收到之后,返回syn+ack,只要收到ack,客户端就可以认为连接建立。

同理,只要服务器收到客户端的ack报文,则服务器端也认为连接成立。

客服端并不需要对自己发送的ack进行等待,因为它之前就认为建立了连接,根本不需要等待服务器发送的ack报文




这个角度,你的说法,我不同意,三次是两方都确认连接的最少次数。

你从防止防SYN flooding角度考虑的说法,我表示赞同,最后再请教你一个问题,我这个帖子最开始 对关于谢希仁关于两次握手的解释的质疑是否正确?多谢




作者: kkshaq    时间: 2015-06-12 17:07
蛮多肉 发表于 2015-06-12 06:16
在多数情况下2次握手够了

极端情况下,N次握手都不够


三次握手的目的是什么??怎么越讨论越乱 。。。为什么N次握手都不够???我认为各自收到一个ack,连接就认为成立了,所以需要三次。两次不行。
作者: kkshaq    时间: 2015-06-12 17:11
回复 16# cokeboL

最后一个ack包丢失,对建立连接又没有影响。。。
只要收到双方都收到ack报文,就认为连接成立。   
作者: cokeboL    时间: 2015-06-12 17:17
回复 23# kkshaq

不要用tcp规则设计的原因来解释tcp相关规则的合理性,那样解释肯定是合理的

跳出来去想想设计的原因的合理性

否则在讨论的就不是一个东西了,我们在说这个东西的原理不合理,你们却在说用这个原理来解释用这个原理设计的东西的规则是合理的
作者: cokeboL    时间: 2015-06-12 17:17
之前发的帖子也不见了
作者: windoze    时间: 2015-06-12 17:25
本帖最后由 windoze 于 2015-06-12 17:26 编辑

回复 21# kkshaq

如果服务器端不需要客户端第二次发来的ACK就建立链接,那么第二次ACK就没必要发送。
如果服务器端认为它要收到客户端第二次送来的ACK才算是真正建立了链接,但客户端无法知道自己第二次发送的ACK是否被服务器端收到,所以客户端就不知道服务器端是否认为链接已经建立
问题的关键就在于双方要达成共识,但已经证明在不可靠的链路上无法保证能建立这种共识。
作者: zhaohongjian000    时间: 2015-06-12 17:54
回复 20# windoze


    收到第一个包后处于半开状态的连接可以加快回收,虽然不是默认情况也不符合TCP的设计但至少有这个选择。
另外,Linux下半连接放在一个单独的队列中,这其实已经体现出差别了。
作者: windoze    时间: 2015-06-12 18:19
回复 27# zhaohongjian000

你说的这些SYN cookie方案已经不是标准TCP了,再说真要flood起来还是飞速就能搞爆掉。
作者: kkshaq    时间: 2015-06-12 18:43
windoze 发表于 2015-06-12 17:25
回复 21# kkshaq

如果服务器端不需要客户端第二次发来的ACK就建立链接,那么第二次ACK就没必要发送。

恩,懂了。三次握手的共识就是,客服端和服务器都要获知对方已经建立连接,这种情况下,才是连接成功。

然而在链路不可靠的时候,最后一次ack总会丢失,导致双方都获知对方已经建立连接的情况,不可能发生。


两次握手本身就不是为了建立可靠连接,所以也就不需要双方都得获知对方已经建立连接(也就是你说的共识),三次握手本意是想双方获知对方已经建立连接(目的是建立可靠连接),但是实际上不可能成功。



不知道,我理解的是否有误??
作者: windoze    时间: 2015-06-12 20:32
回复 29# kkshaq

没错啊,三次握手基本上是个两头不沾的方案,现在还用纯粹是尾大不掉,要是不考虑兼容性问题造就全升级SCTP了。
作者: cokeboL    时间: 2015-06-12 21:33
回复 31# windoze


    SCTP是基于报文?每次读或写都是一整个?
作者: windoze    时间: 2015-06-12 22:50
回复 31# cokeboL

一个SCTP链接包含多个channel,每个channel相当于一个TCP链接。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2