-
Notifications
You must be signed in to change notification settings - Fork 840
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
通俗大白话来理解TCP协议的三次握手和四次分手 #14
Comments
学习记录一下笔记,多看看,多领会,切勿浮躁一口吃成胖子。 |
向大神学习 |
通俗易懂 |
👍 |
你好 我想问一下为什么客户端发送seq = x后服务器发送ack = x + 1而不是ack = x + 2, ack = x + 3等等?? |
如果你是TCP/IP协议规则的制定人,你可以让ack = x + 1000都没问题,一切规范都是人为制定的,当初就是这么规定的,ack = x + 1,ack = x + 2, ack = x + 3这三种是一个效果,它们是平行的,没有任何区别,其实只要明白,制定这个规则的目的主要用来解决不丢包的问题,明白这个就行了 |
受教了谢谢 |
受教,受我一拜 |
学习了 |
好文!! |
tcp传输数据以字节为单位,ack+1是代表之前的数据已经接收了,期望下次接收从下一个字节开始的数据包 |
GitHub大神多。 |
|
厉害了! |
收藏一个👨🏿💻 |
奋斗的小石头 |
值得学习,上次面试到这题,答的很水 |
总结的不错!star |
多谢大神总结,面试的时候u被问到这个问题了,理解的还不是很透彻。 |
感谢分享! |
深入浅出 |
666 |
服务器发送ack= x+1,表示序号x(包含x)以前的包都已正常接收,服务器下次期待收到的包的序号为x+1 |
SYN、ACK是一个标记位,tcp包头中还有一个确认应答号字段,一般表示为ACK+包序号 |
可以介紹一下QUIC協議為甚麼可以簡化握手嗎 |
老哥,图裂了 |
其实应该是三向握手,而不是三次握手,三个报文结合起来才是一次握手 |
看过 “TCP三次握手四次挥手详解” https://zhuanlan.zhihu.com/p/40013850 文章和《图解TCP/IP》数据TCP首部格式内容之后此处ack应该是确认应答号(Acknowledgement Number)而不是首部控制位的ACK。两者关系是当控制位ACK=1时,确认应答号字段变为有效。确认应答号表示下一次应该收到的数据序列号。发送端收到的这个确认应答以后可以认为在这个序列号以前的数据都已经被正常接收。第二次握手数据应该是:SYN=1,ACK=1,Seq=Y,AckNum=x+1,第三次握手数据应该是:Acknum=y+1,SYN=0,ACK=1。不知道个人理解的是否正确,希望大家多交流。三次握手正确图应该是上面有位老哥提供的图:#14 (comment) |
如果sequence numbers绑定到整个网络时钟,是不是就不需要三次握手这个步骤了??? |
好文马克学习 |
你可以看下这个ack报文的意思,简单来说是确认收到了滴多少个字节 |
ACK是6个标志位中的一个,值是0或1,1表示确认号有效,0表示无效。可以写作ACKbit=1; |
图呢图呢 被谁吃了 |
赞一个啊 收藏了 |
666 |
学习了! |
图挂了 |
有一个小小的问题,两次握手会让server浪费资源,请问这个具体浪费的是哪些资源?是连接建立过程中的一些文件读写开销吗? |
还可以这样写博客,学到了 |
图画的很风趣 |
最近在恶补计算机网络方面的知识,之前对于TCP的三次握手和四次分手也是模模糊糊,对于其中的细节更是浑然不知,最近看了很多这方面的知识,也在系统的学习计算机网络,加深自己的CS功底,就把看过的一些比较好的东西和自己的一些理解二次加工组织一下然后交流分享,一起学习进步,对了这个面试好像经常问到。
原文收录在我的 GitHub博客 (https://github.com/jawil/blog) ,喜欢的可以关注最新动态,大家一起多交流学习,共同进步,以学习者的身份写博客,记录点滴。
通俗理解:
但是为什么一定要进行三次握手来保证连接是双工的呢,一次不行么?两次不行么?我们举一个现实生活中两个人进行语言沟通的例子来模拟三次握手。
引用网上的一些通俗易懂的例子,虽然不太正确,后面会指出,但是不妨碍我们理解,大体就是这么个理解法。
第一次对话:
老婆让甲出去打酱油,半路碰到一个朋友乙,甲问了一句:哥们你吃饭了么?
结果乙带着耳机听歌呢,根本没听到,没反应。甲心里想:跟你说话也没个音,不跟你说了,沟通失败。说明乙接受不到甲传过来的信息的情况下沟通肯定是失败的。
如果乙听到了甲说的话,那么第一次对话成功,接下来进行第二次对话。
第二次对话:
乙听到了甲说的话,但是他是老外,中文不好,不知道甲说的啥意思也不知道怎样回答,于是随便回答了一句学过的中文 :我去厕所了。甲一听立刻笑喷了,“去厕所吃饭”?道不同不相为谋,离你远点吧,沟通失败。说明乙无法做出正确应答的情况下沟通失败。
如果乙听到了甲的话,做出了正确的应答,并且还进行了反问:我吃饭了,你呢?那么第二次握手成功。
通过前两次对话证明了乙能够听懂甲说的话,并且能做出正确的应答。 接下来进行第三次对话。
第三次对话:
甲刚和乙打了个招呼,突然老婆喊他,“你个死鬼,打个酱油咋这么半天,看我回家咋收拾你”,甲是个妻管严,听完吓得二话不说就跑回家了,把乙自己晾那了。乙心想:这什么人啊,得,我也回家吧,沟通失败。说明甲无法做出应答的情况下沟通失败。
如果甲也做出了正确的应答:我也吃了。那么第三次对话成功,两人已经建立起了顺畅的沟通渠道,接下来开始持续的聊天。
通过第二次和第三次的对话证明了甲能够听懂乙说的话,并且能做出正确的应答。
可见,两个人进行有效的语言沟通,这三次对话的过程是必须的。
为了保证服务端能收接受到客户端的信息并能做出正确的应答而进行前两次(第一次和第二次)握手,为了保证客户端能够接收到服务端的信息并能做出正确的应答而进行后两次(第二次和第三次)握手。
这个例子举得挺好的。不过个人感觉为什么是三次而不是二次,不是因为为了证明甲能听懂乙并回应(第二次乙能正确的响应甲说明俩人之间沟通已无障碍了),而是怕出现以下情况而浪费感情。这个情景是这样的(例子有点不实际意会就好):甲在路上跟乙打招呼,由于刮风什么的这句活被吹跑了,然后甲又跟打了个招呼,乙听到了并作出了回应。此时不管是三次握手还是两次握手两个人都能愉快的沟通。0.1秒后俩人四次挥手告别了。此时被风刮跑的那句话又传到了乙的耳朵里,乙认为甲又要跟他沟通,所以做出了响应的回应。(问题出现了)假如采用2次握手,乙就认定了甲要跟他沟通,于是就不停的等,浪费感情。可如果是采用3次握手,乙等了一会后发现甲没有回应他就认为甲走了然后自己也就走了!
这就很明白了,其实第三步是防止了乙的一直等待而浪费自己的时间,而不是为了保证甲能够正确回应乙的信息。。。后面的也会讲到。
引用知乎上的别人引用的一个回答,从另外一个角度阐释:
上面的纯属大白话娱乐讲解,可能还有偏差,例子可能有点不得体。在我们真正了解TCP的三次握手和四次分手之前,必须了解一些基本的概念,最后和这大白话例子对比结合一下理解,说不定就会顿时融会贯通。
HTTP连接
HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。
HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
1)在HTTP 1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。
2)在HTTP 1.1中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。
由于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”,要保持客户端程序的在线状态,需要不断地向服务器发起连接请求。通常 的做法是即时不需要获得任何数据,客户端也保持每隔一段固定的时间向服务器发送一次“保持连接”的请求,服务器在收到该请求后对客户端进行回复,表明知道 客户端“在线”。若服务器长时间无法收到客户端的请求,则认为客户端“下线”,若客户端长时间无法收到服务器的回复,则认为网络已经断开。
SOCKET原理
套接字(socket)概念
套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应 用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。
建立socket连接
建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。
套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发 给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
SOCKET连接与TCP连接
创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。
Socket连接与HTTP连接
由于通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网 络应用中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。
而HTTP连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。
很多情况下,需要服务器端主动向客户端推送数据,保持客户端与服务器数据的实时与同步。此时若双方建立的是Socket连接,服务器就可以直接将数 据传送给客户端;若双方建立的是HTTP连接,则服务器需要等到客户端发送一次请求后才能将数据传回给客户端,因此,客户端定时向服务器端发送连接请求, 不仅可以保持在线,同时也是在“询问”服务器是否有新的数据,如果有就将数据传给客户端。TCP(Transmission Control Protocol) 传输控制协议
TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接:
TCP是什么?
TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
具体的关于TCP是什么,我不打算详细的说了;当你看到这篇文章时,我想你也知道TCP的概念了,想要更深入的了解TCP的工作,我们就继续。它只是一个超级麻烦的协议,而它又是互联网的基础,也是每个程序员必备的基本功。首先来看看OSI的七层模型:
我们需要知道TCP工作在网络OSI的七层模型中的第四层——Transport层,IP在第三层——Network层,ARP在第二层——Data Link层;在第二层上的数据,我们把它叫Frame,在第三层上的数据叫Packet,第四层的数据叫Segment。 同时,我们需要简单的知道,数据从应用层发下来,会在每一层都会加上头部信息,进行封装,然后再发送到数据接收端。这个基本的流程你需要知道,就是每个数据都会经过数据的封装和解封装的过程。 在OSI七层模型中,每一层的作用和对应的协议如下:
TCP是一个协议,那这个协议是如何定义的,它的数据格式是什么样子的呢?要进行更深层次的剖析,就需要了解,甚至是熟记TCP协议中每个字段的含义。哦,来吧。
TCP头部
其中 ACK SYN 序号 这三个部分在以下会用到,它们的介绍也在下面。
上面就是TCP协议头部的格式,由于它太重要了,是理解其它内容的基础,下面就将每个字段的信息都详细的说明一下。
Source Port和Destination Port:分别占用16位,表示源端口号和目的端口号;用于区别主机中的不同进程,而IP地址是用来区分不同的主机的,源端口号和目的端口号配合上IP首部中的源IP地址和目的IP地址就能唯一的确定一个TCP连接;
Sequence Number:用来标识从TCP发端向TCP收端发送的数据字节流,它表示在这个报文段中的的第一个数据字节在数据流中的序号;主要用来解决网络报乱序的问题;
Acknowledgment Number:32位确认序列号包含发送确认的一端所期望收到的下一个序号,因此,确认序号应当是上次已成功收到数据字节序号加1。不过,只有当标志位中的ACK标志(下面介绍)为1时该确认序列号的字段才有效。主要用来解决不丢包的问题;
Offset:给出首部中32 bit字的数目,需要这个值是因为任选字段的长度是可变的。这个字段占4bit(最多能表示15个32bit的的字,即4*15=60个字节的首部长度),因此TCP最多有60字节的首部。然而,没有任选字段,正常的长度是20字节;
TCP Flags:TCP首部中有6个标志比特,它们中的多个可同时被设置为1,主要是用于操控TCP的状态机的,依次为URG,ACK,PSH,RST,SYN,FIN。每个标志位的意思如下:
暂时需要的信息有:
ACK : TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1
SYN(SYNchronization) : 在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文。对方若同意建立连接,则应在响应报文中使SYN=1和ACK=1. 因此, SYN置1就表示这是一个连接请求或连接接受报文。
FIN (finis)即完,终结的意思, 用来释放一个连接。当 FIN = 1 时,表明此报文段的发送方的数据已经发送完毕,并要求释放连接。
三次握手的过程:
多么清晰的一张图,当然了,也不是我画的,我也只是引用过来说明问题了。
完成了三次握手,客户端和服务器端就可以开始传送数据。以上就是TCP三次握手的总体介绍。
那四次分手呢?
当客户端和服务器通过三次握手建立了TCP连接以后,当数据传送完毕,肯定是要断开TCP连接的啊。那对于TCP的断开连接,这里就有了神秘的“四次分手”。
至此,TCP的四次分手就这么愉快的完成了。当你看到这里,你的脑子里会有很多的疑问,很多的不懂,感觉很凌乱;没事,我们继续总结。
为什么要三次握手
在谢希仁著《计算机网络》书中同时举了一个例子,如下:
这就很明白了,防止了服务器端的一直等待而浪费资源。
为什么要四次分手
那四次分手又是为何呢?TCP协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。TCP是全双工模式,这就意味着,当主机1发出FIN报文段时,只是表示主机1已经没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完毕了;但是,这个时候主机1还是可以接受来自主机2的数据;当主机2返回ACK报文段时,表示它已经知道主机1没有数据发送了,但是主机2还是可以发送数据到主机1的;当主机2也发送了FIN报文段时,这个时候就表示主机2也没有数据要发送了,就会告诉主机1,我也没有数据要发送了,之后彼此就会愉快的中断这次TCP连接。如果要正确的理解四次分手的原理,就需要了解四次分手过程中的状态变化。
实例:
TCP的作用是流量控制,主要是控制数据流的传输。下面以浏览网页为例,根据自身理解来解释一下这个过程。(注:第二个ack属于代码段ack位)
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。
第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主 动关闭连接之前,TCP 连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”(过程就不细写了,就是服务器和客 户端交互,最终确定断开)
对应的实例
IP 192.168.1.116.3337 > 192.168.1.123.7788: S 3626544836:3626544836
IP 192.168.1.123.7788 > 192.168.1.116.3337: S 1739326486:1739326486 ack 3626544837
IP 192.168.1.116.3337 > 192.168.1.123.7788: ack 1739326487,ack 1
第一次握手:192.168.1.116发送位码syn=1,随机产生seq number=3626544836的数据包到192.168.1.123,192.168.1.123由SYN=1知道192.168.1.116要求建立联机;
第二次握手:192.168.1.123收到请求后要确认联机信息,向192.168.1.116发送ack number=3626544837,syn=1,ack=1,随机产生seq=1739326486的包;
第三次握手:192.168.1.116收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,192.168.1.116会再发送ack number=1739326487,ack=1,192.168.1.123收到后确认seq=seq+1,ack=1则连接建立成功。
我想你应该懂了
总结到这里,也该结束了,但是对于TCP的学习远还没有结束。TCP是一个非常复杂的协议,这里稍微总结了一下TCP的连接与断开连接是发生的事情,其中还有很多的“坑”,让我们后续有时间再继续填吧。好了,完毕!
搬运文章
TCP三次握手详解及释放连接过程
首先简单介绍一下TCP三次握手
TCP 为什么是三次握手,为什么不是两次或四次?
最后推荐一个学习HTTP的github项目地址:我自己提炼的关于《HTTP权威指南》每章的知识点总结!
The text was updated successfully, but these errors were encountered: