jjzjj

TCP协议内部工作机制一(确认应答,超时重传,连接管理)

白杨783 2023-10-27 原文

目录

TCP报文结构

TCP的首部长度

保留(6位)

TCP特点

TCP内部的工作机制

一确认应答

超时重传

连接管理

建立建立(三次握手)

 TCP断开连接(四次挥手)


TCP报文结构

 TCP的报文结构中,16位源端口,16位目的端口,16位校验和和UDP是一样的,本篇文章就暂不介绍了,可参考俺之前写的UDP协议详解,

TCP的首部长度

TCP的首部长度是指TCP的报头长度,TCP报头的长度是可变的,因为在TCP报头中有选项这一栏,它是可有可无的,如果不加选项TCP报头是固定长度20字节,因此我们也可以算出选项长度:报头长度-20字节.另外注意4位首部长度4个bite位,范围是0->15,单位是4字节,也就是说如果4位首部长度显示的是5,说明这个报头没有加选项,如果4位首部长度是6,说明报头一共24个字节,选项长度为4字节.

保留(6位)

此处TCP的6位保留位为了以后TCP扩展用的,方便以后扩展升级,给报头添加一些新的部分,就可以直接拿这些保留位就好了


其它部分会在接下来的TCP协议工作原理中介绍.

TCP特点

有连接,可靠,面向字节流,全双工

TCP内部的工作机制

一确认应答

确认应答是TCP实现可靠传输最核心机制,可靠传输不是说把消息100%发送给对方(由于网络物理等因素干扰,不可能实现),而是,当我们成功把数据发送给对方,我们知道发送成功了,当我们没有把数据发送给对方,我们能知道发送失败了

简单来说就是A给B发了个消息,B收到后就会返回一个应答报文(ack),此时A收到应答后,就知道刚刚发的数据已经顺利发送给了B

序号和确认序号

 

 同样我给hxd发消息,但是我可能是连续发俩条消息,我发第二天消息的时候没有等第一条消息的ack,hxd收到我的消息就立即回应

 此时就可能产生歧义,站在我的视角来看,我说走,上号,hxd的回答是滚犊子,我说"我是恁爹",hxd的回答是好啊,好啊.

由于网络俩个主机之间路线有多条,数据报1数据报2走的可能是不同的路线,数据报1的转发路径上的路由器/交换机和数据报2的路由器/交换机可能不一样,有的转发速率快,有的转发速率慢,此时俩个数据报到达的顺序可能就发生改变,就可能会发生后发先至这种情况!此时我们就需要考虑如何规避这种顺序错乱带来的歧义.

 当我们使用序号确认序号,就不怕顺序错乱了,即使顺序错乱,因为有序号和确认序号我们也不会产生歧义

任何一条数据(包括应答报文)都是有序号的,确认序号只有应答报文有(普通报文确认序号字段无意义),如果上面的报文结构图中ACK显示的是1,则表示是应答报文,如果是0,则表示不是应答报文

TCP的序号是面向字节流的,TCP的序号是按照字节来编号的

总结,我们通过确认应答机制,通过应答报文来让发送发知道传输是否成功,进一步引入序号和确认序号,针对多组数据进行区分

超时重传

如果我们发送的数据,丢包(发送发发给接受方的数据丢了)了怎么办? 

丢包分为俩种情况,1是发送方发送的数据丢了,2是接受方返回的应答报文(ack)丢了,这俩种情况,在发送方的视角是分不清的,得到的结果都是发送方没有收到接受方的应答报文.所以发送方都会认为是发送的数据丢了

此时就会有TCP的重传机制,TCP有一个时间阈值,发送方发了一个数据后,就会等待ACK,此时开始计时,如果在时间阈值范围内没有收到ACK,就认为是丢包了,就会重新给接受方发送数据

当然,对于接收方发送返回的应答报文丢了,发送方重新发送数据.此时接收方就收到了2份同样的数据,这种情况会有特殊处理(如果不处理,就可能会发生一个支付请求,支付俩次这种情况),TCP存在一个"接受缓冲区"这样的存储空间(接收方操作系统内核里的一段内存),每个TCP,socket对象,都有一个接收缓存区(也有一个发送缓冲区),主机B收到主机A的数据,其实B的网卡已经读到数据了,把这个数据放到B对应的socket的接收缓冲区中(此处的接收缓冲区就相当于是一个阻塞队列),根据数据的序号,TCP很容易识别当前的俩条数据是否重复,如果重复就把后来的这份重复的数据丢了,这样就保证read读到的数据,一定是不重复

总结:由于接收缓冲区序号的存在(接收的数据都是先放在接收缓冲区的,如果发生后发先至也没关系,由于序号的存在,我们很容易接收缓冲区给数据重新排序去重),即使数据重复了,顺序错乱了,接收方也能很好的处理.        

重传的数据是否可能又丢包了?这是有可能的,因此超时重传可能会重传N次,当然N不会是一个很大的数字,当重传几次都丢包,此时再重传意义也不大了.(很可能是因为网络出现重大故障).因此当重传到一定次数后,此时就不会重传了,视为网络出现故障,接下来TCP会尝试重置连接(相当于断开连接,重连),如果还是失败,就彻底断开连接了,另外重传的时候,第一重传的时间间隔和第二次重传的时间间隔不一样,重传的轮次越大,间隔越大

TCP的可靠传输就是通过 确认应答 + 超时重传 来体现的,其中确认应答描述的是传输顺利的情况,超时重传描述的是传输出现问题的情况 

连接管理

TCP建立连接
A和B建立连接,A中就有一部分存储空间存储了B的IP和端口,B中也有一部分空间存储了A的IP和端口,这俩部分信息被维护好了,此时A和B就建立了连接,而保存这部分信息的储存空间(数据结构)也称为 连接

TCP断开连接

A和B把自己储存的连接信息删了,此时就称为断开连接

那我们是如何具体的建立连接 和 断开连接的呢?

建立建立(三次握手)

通信双方需要各自记录对方的信息,彼此之间相互认同

SYN:客户端服务器发起的建立连接请求称为SYN,也叫同步报文段

这里为什么要把中间俩次的响应和请求合并到一起?

这俩次交互的时机相同,都是操作系统内核收到建立连接请求的时候,返回响应的同时也会给对方发送一个建立连接的请求 .另外,每次交互都需要封装和分用,交互成本很高,我把俩次交互合并成一次这样只用分装分用一次就可以了.

俩次握手能否完成建立连接的过程?

如果只有俩次,比如这里最后A没有给B返回一个ACK,在A的视角是可以的,知道了A保存至了B的信息,并且知道B保存了自己的信息,但在B的视角,B只知道自己保存了A的信息,但不知道A是否保存了自己的信息.另外三次握手还有个作用是,验证通信双方各自的发送能力和接收能力是否正常,如果是俩次握手,B是不知道自己的发送能力是否正常的

三次握手的意义:

1.让通信双方各自建立对对方的"认同"(保存了对方的信息)

2.验证通信双方各自的接收能力和发送能力

3.在握手的过程中,双方来协商一些重要参数

TCP在建立连接阶段的俩个状态

1.LISTEN
服务器的状态,表示服务器已经准备就绪,随时可以有客户端来建立连接

2.ESTABLISHED
客户端服务器都有的状态,表示连接建立完成,接下来可以正常通信了

 TCP断开连接(四次挥手)

四次挥手和三次握手类似,都是通信双方向对方发起一个断开连接的请求,再各自给对方一个回应

 这里四次挥手能不能变成三次挥手呢(中间的ACK和FIN能不能合并)

不能,FIN的发起不是由内核控制的,而是由应用程序调用socket的close方法(或者进程退出)才会触发FIN.ACK则是,当收到FIN,操作系统内核就会立即返回一个ACK,所以FINACK发送的时机不同,这俩者之间会有一个时间差,服务器的程序执行到了对应的close方法才会触发FIN.当然如果执行程序执行close刚好和返回ACK的时机一样,此时也是可以合并的

TCP在断开连接阶段的俩个状态

1.CLOSE_WAIT
出现在被动断开连接的一方,表示等待关闭(等待调用close方法关闭socket)

2.TIME_WAIT
出现在主动发起断开连接的一方,假设是A是主动断开的一方,当A进入TIME_WAIT,相当于四次挥手已经挥完了.此时这里的TIME_WAIT要保持当前的TCP连接状态,不要立即释放.因为此时最后一个ACK刚刚发出去,还不确定有没有丢包,因此TIME_WAIT会等一段时间,之后如果没有收到重传的FIN,就认为最后一个ACK没有丢包,就彻底释放连接了(如果这里不保持连接状态,立即释放,如果最后一个ACK丢包了,连接断了,B是没法向A重传FIN的).TIME_WAIT会保持2MSL,意思是A如果经历了2MSL这个时间还没有收到重传的FIN,就认为这个ACK正常到达了(B没有重传FIN),MSL指的是,互联网上任意俩个节点数据传输消耗的最大时间,通常情况下这个值是60s

有关TCP协议内部工作机制一(确认应答,超时重传,连接管理)的更多相关文章

  1. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  2. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  3. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

  4. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

  5. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  6. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  7. ruby - JetBrains RubyMine 3.2.4 调试器不工作 - 2

    使用Ruby1.9.2运行IDE提示说需要gemruby​​-debug-base19x并提供安装它。但是,在尝试安装它时会显示消息Failedtoinstallgems.Followinggemswerenotinstalled:C:/ProgramFiles(x86)/JetBrains/RubyMine3.2.4/rb/gems/ruby-debug-base19x-0.11.30.pre2.gem:Errorinstallingruby-debug-base19x-0.11.30.pre2.gem:The'linecache19'nativegemrequiresinstall

  8. ruby - `rescue $!` 是如何工作的? - 2

    我知道全局变量$!包含最新的异常对象,但我对下面的语法感到困惑。谁能帮助我理解以下语法?rescue$! 最佳答案 此构造可防止异常停止您的程序并使堆栈跟踪冒泡。它还会将该异常作为值返回,这很有用。a=get_me_datarescue$!在此行之后,a将保存请求的数据或异常。然后您可以分析该异常并采取相应措施。defget_me_dataraise'Nodataforyou'enda=get_me_datarescue$!puts"Executioncarrieson"pa#>>Executioncarrieson#>>#更现实的

  9. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  10. ruby-on-rails - Rails 优雅地处理超时 session ? - 2

    使用rails4,ruby2。我在rails配置中为我的cookiesession设置了30分钟的超时时间。问题是,如果我转到表单,让session超时,然后提交表单,我会收到此ActionController::InvalidAuthenticityToken错误。如何在Rails中优雅地处理这个错误?比如说,重定向到登录屏幕? 最佳答案 在您的ApplicationController:rescue_fromActionController::InvalidAuthenticityTokendoredirect_tosome_p

随机推荐