TCP三向握手的工作原理如下:

Client ------SYN-----> Server
Client <---ACK/SYN---- Server
Client ------ACK-----> Server


为什么不这样呢?

Client ------SYN-----> Server
Client <-----ACK------ Server


评论

为什么我们甚至需要握手?为什么消息不能与第一个数据包一起发送?

如果要跳过握手,则可以改用UDP。

@Mehrdad,如果您有自己的问题,请使用页面顶部的“提问”链接发布您自己的问题。

@YLearn:对不起,这并不是我自己的问题,而是要激发读者给出比问题中所讲内容更深入的答案。

不要忘记TCP快速打开(RFC 7413)

#1 楼

将握手分解为实际操作。

在TCP中,双方使用序列号来跟踪发送的内容。实际上,它最终是发送的所有内容的运行字节数。接收方可以使用对方讲话者的序列号来确认已收到的内容。

但是序列号不是从0开始。它以ISN(初始序列号)开始。随机选择的值。由于TCP是双向通信,因此双方都可以“讲话”,因此双方都必须随机生成一个ISN作为其起始序列号。反过来,这意味着双方都需要将其开始的ISN通知另一方。

因此,您将以以下事件顺序结束,以开始Alice和Bob之间的TCP对话: >
Alice ---> Bob    SYNchronize with my Initial Sequence Number of X
Alice <--- Bob    I received your syn, I ACKnowledge that I am ready for [X+1]
Alice <--- Bob    SYNchronize with my Initial Sequence Number of Y
Alice ---> Bob    I received your syn, I ACKnowledge that I am ready for [Y+1]


注意,发生了四个事件:


Alice选择一个ISN并将其与Bob同步。
Bob确认了ISN。
Bob选择一个ISN并将其与Alice同步。
Alice确认了ISN。

实际上,中间的两个事件(#2和#3)发生在同一数据包中。使数据包成为SYNACK的原因仅仅是在每个TCP标头中打开或关闭的二进制标志,因此没有什么可以防止在同一数据包上同时启用这两个标志。因此,三向握手最终变为:

Bob <--- Alice         SYN
Bob ---> Alice     SYN ACK 
Bob <--- Alice     ACK     


注意两个方向上的“ SYN”和“ ACK”两个实例,每个实例之一。
/>

所以回到您的问题,为什么不只使用双向握手呢?简短的答案是因为双向握手只会允许一方建立ISN,而另一方承认它。这意味着只有一方可以发送数据。

但是TCP是双向通信协议,这意味着任何一端都应该能够可靠地发送数据。双方都需要建立一个ISN,并且双方都需要确认对方的ISN。

因此,实际上,您对双向握手的描述完全正确,但是在每个方向上都是如此。因此,发生了四个事件。同样,中间两个标志出现在同一数据包中。因此,三个数据包参与了完整的TCP连接启动过程。

评论


为什么我们根本需要ISN?人类不需要它,为什么要使用计算机?有证据吗,还是因为方便才拿到它们?

–user541686
2015年11月4日在20:52

@Mehrdad:您需要序列号才能进行重新传输,以使其正常工作(或根本不工作)。由于序列预测攻击,ISN不能只是零。

–凯文
15年11月4日在21:04

@Mehrdad聊天室不一定必须是“实时”的,我们可以互相留言。我之所以将其转至其他地方,是因为您现在在问另一个问题。 OP询问“为什么是3握手而不是2握手”,但是现在您在问“为什么我们根本需要序列号”,这是不同的。我认为我们应该在聊天中讨论另一个问题,而不是使该线程出轨。或者,您可以发布一个新问题,我敢肯定,它将获得一些不错的答案。

–艾迪
15年11月4日在22:19

简明扼要的答案。读“ ACK SYN”从根本上来说是错误的,但您甚至解释了+1。

– Liilienthal
2015年11月5日,12:52

根据RFC 793,传输控制协议:“三向握手的主要原因是为了防止旧的重复连接启动引起混乱。”

–罗恩·莫潘♦
2015年11月5日在18:05

#2 楼

三向握手是必要的,因为双方都需要同步在传输过程中使用的段序列号。为此,它们每个都发送(依次)序列号设置为随机值n的SYN片段,然后对方通过序列号设置为n + 1的ACK片段确认对方。

评论


为什么需要确认?

–PaŭloEbermann
15年11月4日在21:18

@PaŭloEbermann:因为否则服务器不知道客户端是否曾经收到过SYN,因此客户端收到该消息很重要。

–鸭鸭
2015年11月4日在21:21

@PaŭloEbermann为了证明这一点,ACK步骤是用[X + 1]进行确认。 -引用埃迪(Eddie)对他的回答的评论。

–smwikipedia
2015年11月5日在8:22



#3 楼

为了使连接正常工作,每一端都需要验证是否可以将数据包发送到另一端。确保您将数据包发送到另一端的唯一方法是从他们那里获得一个数据包,根据定义,除非您发送的数据包通过,否则该数据包将不会被发送。 TCP本质上为此使用两种消息:SYN(请求证明此数据包已通过)和ACK(仅在SYN通过后才发送,以证明SYN通过了)。实际上有第三种信息,但是我们稍后会谈到。

在开始连接之前,双方都不了解对方。客户端将SYN数据包发送到服务器,以请求证明其消息可以通过。这不会告诉任何人任何信息,但这是握手的第一步。

如果SYN通过,则服务器知道客户端可以向其发送数据包,因为它可以刚发生。但这并不能证明服务器可以将数据包发送回:客户端可以出于多种原因发送SYN。因此,服务器需要向客户端发送两条消息:一个ACK(证明SYN通过了)和一个SYN(请求自己的ACK)。 TCP将这两个消息合并为一个-SYN-ACK消息(如果愿意),以减少网络流量。这是握手的第二步。

由于SYN-ACK是ACK,因此客户端现在确定可以将数据包发送到服务器。并且因为SYN-ACK是SYN,所以它也知道服务器希望证明此消息已通过。因此它发送回一个ACK:这次只是一个普通的ACK,因为它不再需要证明其数据包可以通过的证据。这是握手的最后一步:客户端现在知道数据包可以双向传输,并且服务器即将解决此问题(因为它知道ACK将通过)。

一旦该ACK通过,现在服务器便知道可以将数据包发送到客户端。它还知道客户端知道这一点,因此它可以立即开始发送数据。握手完成。我们有一个好的频道。

好吧,严格来说,我们不能确定我们有一个好的频道。仅因为此顺序的数据包通过并不能严格保证其他人会通过。我们无法证明,如果不发送无限数量的SYN和ACK,那么将一事无成,因此这不是一个实际的选择。但是实际上,三个步骤对于大多数目的来说已经足够了。

评论


这是不正确的:“一个ACK(仅在响应SYN时发送,因此证明SYN通过了)。”只有从两端发送的第一个数据包都设置了SYN标志,而除三向握手的第一个数据包以外的所有数据包都设置了ACK标志。第一个数据包无法进行ACK,因为第二方尚未进行SYNed,但是第一个数据包之后的每个数据包都必须ACK,无论对方是否已发送回任何数据,都必须ACK。

– Monty Harder
16-10-31在14:43

谢谢。重措词:SYN通过后才发送ACK,而不仅仅是响应SYN而发送。

–最傻的
16-10-31在15:53

这是最好的答案,可以从逻辑上解释为什么我们甚至需要第三条消息。谢谢,傻瓜。

–Parth Patel
19 Mar 10 '19 at 18:55



#4 楼

实际上,三向握手并不是建立TCP连接的唯一方法。也允许同时进行SYN交换:http://www.tcpipguide.com/free/t_TCPConnection EstablishmentmentProcessTheThreeWayHandsh-4.htm

这可以看作是两次双向双向握手。

评论


好的一点是,但是这非常罕见,因为两个设备都必须使用相同的源/目标端口,并且两个设备都需要在另一个接收SYN之前发送SYN。即使发生这种情况,它也要发送四个数据包,这比传统的三向握手所需的三个数据包还多。最终只有在总体时间上稍微加快设置速度的可能性,而总体效率却降低了(需要传输的数据包增加33%)。

– YLearn♦
2015年11月5日在16:39

#5 楼

TCP连接是双向的。这意味着它实际上是一对单向连接。发起方发送SYN,响应方发送ACK:一个单纯形连接开始。 “然后”响应者发送SYN,发起者发送ACK:另一个单纯形连接开始。两个单工连接形成一个双工TCP会话,同意吗?因此,从逻辑上讲,涉及四个步骤;但是由于SYN和ACK标志是TCP报头的不同“字段”,因此可以同时设置它们-第二步和第三步(四个步骤)被组合在一起,因此从技术上讲,存在三个数据包交换。根据您的建议,每个单工(半)连接都使用2路交换。

#6 楼

如果服务器和客户端要创建连接,则需要确认四件事:


服务器需要确认他可以从客户端接收数据包
客户端需要确认他可以接收数据包从服务器
客户端需要确认的东西:服务器可以从客户端接收数据包
服务器需要确认的东西:客户端可以从服务器接收数据包

Client ------SYN-----> Server之后,规则1为

Client <---ACK/SYN---- Server之后,规则2和3被确认。

因此,需要第三个数据包来确认规则4。

#7 楼

完全没有必要。很明显,一条短消息只需要向服务器发送一个包含开始+消息的数据包,并向后一个确认它的数据包。

前面的答案仅描述了系统,而没有讨论对随机性的需求。序列号等。最初的问题是关于TCP本身的设计的-显然,如果您使用TCP协议,则需要三个消息,因为这是该协议。但是,为什么TCP首先要采用这种方式设计?

我相信最初的想法是客户端和服务器之间没有区别。双方都以双向方式知道对方的端口,并且双方都可以开始通话。而这需要Syns等。

但是,这当然不是今天的用法。服务器在一个众所周知的端口上侦听并“接受”,客户端端口号是临时的。我什至认为在正常操作系统中,等待“接受”的服务器不可能将请求发送到同一客户端端口号上的另一个请求。

(请注意,这与双向启动有关连接,直到今天为止都还没有完成。这与建立连接后通过双向发送双向消息完全不同。)

要解决TCP效率低下的问题,我们使用了HTTP 1.1之类的协议,可以重用多个请求使用相同的连接,因此避免了TCP握手,该握手首先不需要。

但是Http 1.1相对较新。由于PKI算法的成本,SSL / TLS从一开始就需要一种重用会话的方法。因此该协议包括其自己的会话重用机制,该机制在Http 1.1的基础上运行,而HTTP 1.1在TCP的基础上运行。

软件就是这样。混合在一起时产生的效果软糖。

评论


OSI第4层以上的任何内容(例如HTTP,FTP等)在这里都明确不在主题之列。在第1到第4层中,没有客户端/服务器之类的东西。 TCP是对等点之间的连接。是的,上层协议创建了客户端/服务器关系,但是在这里是不合主题的。

–罗恩·莫潘♦
16-5-23在2:10



顺便说一句,HTTP使用TCP,因此TCP握手仍然是必需的。阅读RFC 793传输控制协议以了解其原因。像HTTP这样的协议要求应用程序执行TCP通常对应用程序执行的多路复用。

–罗恩·莫潘♦
16年5月23日在2:18

@RonMaupin最初的问题是为什么?答案是支持一个用例,该用例在实践中从未被上层使用。所以,似乎很相关。

–可伸缩
16年5月23日在2:18

@RonMaupin是的,HTTP使用TCP。我已经澄清了,谢谢。但这在任何意义上都不需要TCP握手。

–可伸缩
16年5月23日在2:20

在这里,应用程序和应用程序层协议明确不在主题之列。 @Eddie回答了这个问题,如果您阅读并理解了TCP RFC,您将了解为什么需要握手。在没有任何支持的情况下,我认为这并没有给您增加任何必要的主张,即握手是不必要的。

–罗恩·莫潘♦
16年5月23日在2:21

#8 楼

在阅读了Eddie的答案(被接受为正确的答案)之后,仍然存在一个问题,为什么第一个主机不能同时为两个ISN分配随机数,而第二个主机只能接受它。使用三向握手的真正原因是为了避免半连接。两向握手的半连接情况:
1)客户端--- SYN->服务器
2)客户端改变了主意,不再想要连接
3)客户端< -X-ACK--服务器// ACK丢失
服务器没有看到重新发送的SYN,因此他认为客户端得到了他的ACK并建立了连接。因此,服务器具有永远不会关闭的连接

评论


实际上,如果主机(客户端和服务器是TCP不了解的应用程序概念)在不存在的连接上接收到ACK或任何流量(您的方案中的步骤3),它将发送RST,而不忽略接收到的段。

–罗恩·莫潘♦
18年5月15日在14:42

@RonMaupin然后让我们假设ACK数据包丢失的情况。

– Sanzhar Yeleuov
18年5月15日在16:34

如果ACK丢失,则步骤1中发起的连接将超时。 RFC 793全面说明了所有类型的场景,包括图表。

–罗恩·莫潘♦
18年5月15日在16:38

@RonMaupin我的意思是,如果我发布的内容保持不变,只是发生了变化,所以ACK丢失了。

– Sanzhar Yeleuov
18年5月15日在16:43



全部在RFC中。在打开连接之前,收到的所有流量都将导致RST。三向握手协商连接参数,因此“服务器”无法将任何内容发送回“客户端”,但它是SYN / ACK,直到从“客户端”接收到ACK。如果丢失了返回到“客户端”的“服务器” SYN / ACK,则“服务器”将重试。 RFC解释了所有这一切。

–罗恩·莫潘♦
18年5月15日在16:49

#9 楼

简单答案:

客户端和服务器都需要知道它们可以连接。

对于客户端:实际上,双向握手就足够了,因为它发送到服务器和服务器发送回。

对于服务器:需要三向握手,因为服务器需要知道它发送回客户端的消息(第二条消息)是否成功。来自客户端的第三条消息证明服务器的消息(第二条消息)成功,因此需要第三条消息。

评论


TCP没有基于应用程序层的服务器/客户端概念。应用程序服务器可能会连接到应用程序客户端(如活动FTP所示)。

– Zac67
2月9日8:57