上章计算机网络的学习整理中整理了Http协议的内容,今天的文章中整理一下tcp协议。html
文章中部分图片来自于网络,侵删算法
首先介绍一下tcp协议, tcp一种可靠的,面向链接的服务,它为端与端之间的进程通讯提供了可靠的数据传输功能,经过流量控制,序号,确认和定时器等功能,tcp可以讲数据按序正确的从原进程传递到目标进程中。缓存
多路复用以及多路分解是由网络层提供的主机到主机交付服务延伸到为运行在主机上的应用程序提供进程到进程的交付服务。一个进程(做为网络应用的一部分)有一个或多个套接字(socket),它至关于从网络向进程传递数据和从进程向网络传递数据的门户。将运输层报文段中的数据交付到正确的套接字的工做称为多路分解(demultiplexing)。而在源主机中从不一样套接字中收集数据块,并为每一个数据块封装上首部信息从而生成报文段,而后将报文段传递到网络层,全部这些工做称为多路复用(multiplexing)。服务器
从上面概念来看,多路复用以及多路分解就是一个对称关系的概念。接下来看下多路复用以及多路分解在传输层封装的报文段中的表现:网络
咱们在开发时候都知道TCP是一个可靠的传输协议,那么为何是可靠的呢?这个可能不少人并不了解。首先咱们来试想一想看可能会发生的问题:并发
这些问题在数据传输中确定时会遇到的,那么该怎么解决这些问题呢?socket
首先看看第一个问题,发生情境多是底层物理部件时候发生问题,致使了分组数据中有概率使一个比特数据从0变成了1。如何处理呢?在《计算机网络-自顶向下》中举了一个情景,我以为挺好:在打电话中,咱们在正常状况就正常对话就能够了,若是对方忽然说话声音听不清了,那么咱们就会让他重复一下上次说的话。那么在第一种问题情境中,咱们也可使用这种方式来处理,这种基于重传的可靠数据传输协议叫自动重传请求协议(ARQ)。tcp
在ARQ中包含三种方式处理比特差错的状况:性能
这三种方式是按序发生的,当发送方发出数据的时候,接收方在接收到的同事进行差错检测,若是出现问题,那么接收方在答复的时候,在数据中带上NAK,反之带上ACK。发送方在拿到响应数据的时候,若是收到NAK时候,则进行重传。这里还得考虑一个问题,万一接收方的反馈也被物理部件影响返回彻底错误的结果了怎么办呢?既然发生了,那么咱们重发一次分组不就行了么,不是ACK的答复,都按照NAK来处理,其实不就处理好了么?经过这种方式是能解决问题,可是可能会形成一个问题:因为发送方不清楚接收方是否收到了数据,因此发两次给接收方可能形成冗余分组的问题。学习
如何却解决冗余分组的问题呢,TCP中会对每个分组带上序号,这样接收方能够去判断是重复数据仍是初始数据,若是接收方最近收到了相同序号的分组,那么就是重复数据了。而且,经过序号的方式,接收方在收到数据的时候可不只能够处理重复数据的问题,也能处理数据顺序的问题,接收方能够按照序号对失序的分组集进行重组传递给接收方应用程序,那么问题二情境也就天然而然解决了。
最后看下问题三,分组数据丢失了怎么办?可能发送方的分组数据丢了没到达接收方手里,也可能接收方返回的响应数据丢了,那么这个时候该怎么处理呢?这个问题其实很简单,咱们针对每一个分组数据设置一个定时器不就完了么。在定时器规定时间内没有获得响应数据,发送方就进行重传的操做就行了。
经过ARQ协议就可以保证数据的可靠传输,可是效率也是须要去重视的,如何在保证数据可靠传输的状况下进行高效的做业呢?
首先考虑最简单的状况,就是串行进行上面的一系列操做,一个分组操做完后才进行下一个分组的传输。这样的方式称之为停等协议。这种协议对于网络利用率实在太差了,咱们能够类比一下若是咱们在一个线程中进行一系列串行I/O的操做,这个咱们是不能接受的。
那么改为类比并发的方式处理确定是更为稳当的,咱们容许发送多个分组无需等待确认,这种技术称之为流水线,经过该技术对可靠传输协议会带来影响以下:
上面的影响TCP的开发人员提出了两种方式去解决:回退N步以及选择重传。
回退N步协议(GBN)也称之为滑动窗口协议,其做用是容许发送方发送多个分组并且无需等待确认,可是受限于流水线中未确认的分组的最大数不能超过N。下面的图中显示了发送方的序号范围:
能够看到在窗口长度范围内有已发送但未确认的数据,以及可用可是未发送的数据,在后面的数据(紫红色)只能等待窗口中的数据发送被确认后才有机会进入窗口中,至关于窗口主动进行了滑动,这也就是GBN称为滑动窗口协议的缘由。
GBN的运行过程以下描述:
GBN好处在于容许发送方发送多个分组并且无需等待确认,可是也存在着很是明显的性能问题,单个分组一旦出了错就会自动重传全部已发送未确认的数据,所以又提出了选择重传协议。
选择重传协议经过让发送发仅仅重传接收方出错的分组,避免没必要要的重传操做。这种个别的,按需的重传要求接收方逐个确认正确接收的分组,再次用窗口长度N来限制流水线中未完成,违背确认的分组数。接收方会接收失序的分组,直到全部丢失的分组被接收到为止,而后按序的交付于上层程序。
选择确认机制能够认为是选择重传以及回退N步协议的综合体,即接收方有选择性的确认失序的报文段,而不是累计确认最后一个正确接收的有序报文段,只重传未被接收方确认过的报文段。更加详细的内容能够看这篇文章,写的很是浅显易懂。
这里总结一下可靠数据传输原理思路图:
首先整理一下该节中会遇到的缩写:
TCP协议是基于可靠数据传输原理,这也是为何上面整理了:靠数据传输原理的相关内容。首先看下TCP报文段结构吧:
TCP的首部为20字节,主要的字段说明以下:
首先介绍一下序号字段,序号的概念创建在传送的字节流之上,一个报文段的序号为报文段首字节流的编号,假设一段字节流为1000字节,每一个报文段大小为200字节,那么第一个报文段序号为0,第二个为200,第三个为400,以此类推。
确认号的概念则是发送方但愿从接送方收到的下一节数据的序号,好比发送方已经从接收方收到了0-200字节的数据,此时发送方再发送一个报文段给接收方,而且带上确认号201,代表但愿收到201以及以后的全部字节。
接下来画个流程图来加深理解一下序号和确认号的概念吧,假设客户端和服务端的字节流的起始序号分别为20和40,而且报文段的字节大小都是1字节:
TCP协议经过三次握手和四次挥手来保证链接的创建与拆除操做。首先看下三次握手:
经过三次握手,双方创建了链接,就能够相互发送/接收数据了。那么为何要三次握手呢?网络得来的答案以下:
为何A还要发送一次确认呢?能够二次握手吗?
主要为了防止已失效的链接请求报文段忽然又传送到了B,于是产生错误。如A发出链接请求,但因链接请求报文丢失而未收到确认,因而A再重传一次链接请求。后来收到了确认,创建了链接。数据传输完毕后,就释放了链接,A工发出了两个链接请求报文段,其中第一个丢失,第二个到达了B,可是第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到链接释放之后的某个时间才到达B,此时B误认为A又发出一次新的链接请求,因而就向A发出确认报文段,赞成创建链接,不采用三次握手,只要B发出确认,就创建新的链接了,此时A不理睬B的确认且不发送数据,则B一致等待A发送数据,浪费资源。
四次挥手用于断开双方的链接,主要流程以下图所示:
该内容来自这位大牛的文章,我只是作搬运工,底下内容的ACK以及ack两个不是特别明白,看计算机网络自顶向下中没有解释,不过不影响理解
为何链接的时候是三次握手,关闭的时候倒是四次握手?
由于当Server端收到Client端的SYN链接请求报文后,能够直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。可是关闭链接时,当Server端收到FIN报文时,极可能并不会当即关闭SOCKET,因此只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端全部的报文都发送完了,我才能发送FIN报文,所以不能一块儿发送。故须要四步握手。
一条TCP链接每一侧的主机都会为该链接创建一个接受缓存来保存数据,当TCP接收到正确的数据的时候就会放入到缓存当中,相关应用程序则会在合适的时间去缓存中读取数据。那么若是发送方发送数据过快致使了接受方的缓存溢出了就会形成问题。
解决该问题的方案就是流量控制,流量控制是一个速度匹配的服务,即便得发送方的发送速率和接收方应用程序的读取速率相匹配。TCP使发送方维护一个窗口的变量来提供流量控制,就是咱们在TCP报文段结构中的接收窗口字段,代表接收方还有多少可用的缓存空间。因为TCP为全双工通讯,因此接收方和发送方各有一个接收窗口。
下面简单看个例子:
拥塞控制主要用于解决网络拥塞的问题,网络拥塞缘由主要在于太多的源想要以太高的速率发送数据。TCP中实现的拥塞控制主要有以下方式:
发送方会维护一个拥塞窗口(cwnd)来控制发送速率
慢启动的原理以下:
当一条TCP链接开始的时候,cwnd的值通常设置为一个MSS,首先传递一个报文段,当接收到该报文段的确认时候,cwnd值就变成2个MSS,而后发送两个报文段,当这两个报文段被确认后,cwnd值就变成4个MSS而后发送4个报文段,以此类推
慢启动呈指数幂的形式增长拥塞窗口,可是也不能无限制的去增长对应的拥塞窗口,慢启动会伴随着一个变量共同使用:ssthresh(慢启动阈值)。当cwnd的值等于ssthresh的时候,就会进入拥塞避免的策略当中去。
当进入拥塞避免的时候,cwnd按线性规律增加。
一条TCP链接有时会因等待重传计时器的超时而空闲较长的时间,慢开始和拥塞避免没法很好的解决这类问题,所以提出了快速重传和快速恢复的拥塞控制方法。
快重算法机制是,丢包了,接收端重复发送丢包前的ACK,发送端每发送一个包过来,接收端就发相同的ACK回去,这个ACK是对丢包以前的确认。当接收端连续收到3个相同的ACK,它就知道发生丢包了,根据ACK序号就能重发丢的包。其并不是取消了重传机制,只是在某些状况下更早的重传丢失的报文段(若是当发送端接收到三个的确认ACK时,则判定分组丢失,当即重传丢失的报文段,而没必要等待重传计时器超时)。
快恢算法主要是跟着快重算法一块儿使用的,因为发送方如今认为网络极可能没有发生拥塞,所以如今不执行慢开始算法,而是把cwnd值设置为慢启动阈值减半后的值,而后开始执行拥塞避免算法,是拥塞窗口的线性增大。
因此拥塞控制的基本流程是以下:
TCP的可靠性应该是相对于UDP不可靠传输来讲的,由于UDP提供的是不可靠的数据报服务,不保证数据报能到达接收端,可能会有丢失;另外处于传输层之下的IP层也是不可靠的,仅提供尽力而为的端到端数据传输服务,不做任何保证。因此TCP的可靠性是指基于不可靠的IP层在传输层提供可靠的数据传输服务,主要是指传输数据不会损坏或丢失,并且全部数据都是按照发送顺序进行传送。实现TCP的可靠传输有如下机制:
https://blog.csdn.net/u014738387/article/details/52046502
https://blog.csdn.net/mxway/article/details/42784495
《计算机网络-自顶向下》
http://www.javashuo.com/article/p-ooymcqhd-mo.html