计算机网络常见基础问题

2019年11月24日00:31:28 发表评论

通常现在的计算机网络都采用一种分层模型来构建,本文也以分层的结构来梳理计算机网络常见面试问题。

层次结构总述

网络体系结构?

有两种模型,一种是7层网络模型,也就是OSI模型,一种是4层模型,也就是TCP/IP模型。

前者模型是从底向上一步一步进行抽象,分别是物理层、数据链路层、网络层、传输层、会话层、表示层,应用层。具体如下图表示,高层是底层的一种抽象。

4层模型是将7层模型进行了浓缩,将底下两层,合并成为了数据链路层,网络层和传输层单独,最上面3层合并成为了应用层,具体对应关系如下图所示

一般现在用到的都是TCP/IP 4层网络模型,和7层模型相比,要简单不少,同时7层模型分层分的太过于细腻,导致实现起来也比较麻烦,而4层模型已经可以较好的满足现实世界中的业务模型,因此 TCP/TP 4 层模型成为了事实上的标准。

OSI模型中,一个协议应该属于哪一层是以什么为标准划分的?

一个协议归属于OSI参考模型哪一层,主要根据该层可以提供什么样的服务。这个服务如果拘泥于一条链路,则为数据链路层;如果服务可以让终端的流量可以跨越路由器的不同接口在互联网穿梭,则为网络层。如果可以提供或可靠、或不可靠端对端服务的,则为传输层。可以给用户提供服务的则为应用层。

最好一个全流程理解计算机网络的例子如下:

浏览器中输入一个URL发生什么,用到那些协议?

浏览器中输入URL,首先浏览器要将URL解析为IP地址,解析域名就要用到DNS协议,首先主机会查询DNS的缓存,如果没有就给本地DNS发送查询请求。DNS查询分为两种方式,一种是递归查询,一种是迭代查询。如果是迭代查询,本地的DNS服务器,向根域名服务器发送查询请求,根域名服务器告知该域名的一级域名服务器,然后本地服务器给该一级域名服务器发送查询请求,然后依次类推直到查询到该域名的IP地址。DNS服务器是基于UDP的,因此会用到UDP协议。

得到IP地址后,浏览器就要与服务器建立一个http连接。因此要用到http协议,http协议报文格式上面已经提到。http生成一个get请求报文,将该报文传给TCP层处理。如果采用https还会先对http数据进行加密。TCP层如果有需要先将HTTP数据包分片,分片依据路径MTU和MSS。TCP的数据包然后会发送给IP层,用到IP协议。IP层通过路由选路,一跳一跳发送到目的地址。当然在一个网段内的寻址是通过以太网协议实现(也可以是其他物理层协议,比如PPP,SLIP),以太网协议需要直到目的IP地址的物理地址,有需要ARP协议。

应用层

应用层包括两个主要的协议:HTTP 和 DNS

HTTP/HTTPS 1.0/1.1/2.0的特点和区别?

HTTPS是基于安全套接字层的超文本传输协议,HTTPS在HTTP应用层的基础上使用安全套接字层作为子层。HTTPS = HTTP + SSL。
HTTP和HTTPS的区别如下: (1) 安全性:HTTP是超文本传输协议,信息是明文传输,容易发生流量劫持和HTTP攻击,HTTPS进行SSL加密传输、身份认证,比HTTP安全; (2) 费用:HTTP免费,HTTPS的CA证书需要一定费用; (3) 端口:HTTP标准端口为80,HTTPS标准端口号为443。 (4) 防劫持:HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题。
HTTP1.0/1.1/2.0的特点和区别如下: (1) HTTP1.0规定浏览器与服务器保持较短时间的链接,链接无法复用,易产生线头阻塞; (2) HTTP1.1支持持久链接,增加请求头和响应头来扩充功能,包括断点续传、缓存处理和host头处理; (3) HTTP2.0支持多路复用、首部压缩、流量控制和服务端推送。

HTTP中,session 和 cookie 区别?禁用cookie后怎么办?

Session是由应用服务器维持的一个服务器端的存储空间,用户在连接服务器时,会由服务器生成一个唯一的SessionID,用该SessionID 为标识符来存取服务器端的Session存储空间。而SessionID这一数据则是保存到客户端,用Cookie保存的,用户提交页面时,会将这一 SessionID提交到服务器端,来存取Session数据。这一过程,是不用开发人员干预的。所以一旦客户端禁用Cookie,那么Session也会失效。

Cookies是服务器在本地机器上存储的小段文本并随每一个请求发送至同一个服务器。IETF RFC 2965 HTTP State Management Mechanism 是通用cookie规范。网络服务器用HTTP头向客户端发送cookies,在客户终端,浏览器解析这些cookies并将它们保存为一个本地文件,它会自动将同一服务器的任何请求缚上这些cookies。

那么,在客户端禁用Cookie的时候,我们要怎么做呢,可以有以下两种方法

1)设置php.ini中的session.use_trans_sid = 1或者在PHP编译时打开–enable-trans-sid选项,让PHP自动通过URL传递session id。

2)如果是虚拟主机或者租用的服务器,无法去修改PHP.ini,那么可以手动通过URL传值,或者通过隐藏表单传递session id。说简单些就是自己去操纵sessionid这个唯一标识符,去鉴别用户即可。

域名解析的过程?DNS的工作过程?

1)检查浏览器缓存中有没有

2)检查本地系统hosts文件中有没有

3)检查本地路由器中有没有

4)ISP的本地DNS服务器:ISP是互联网服务提供商(Internet Service Provider)的简称,ISP有专门的DNS服务器应对DNS查询请求。

5)根服务器:ISP的DNS服务器还找不到的话,它就会向根服务器发出请求,进行递归查询(DNS服务器先问根域名服务器.com域名服务器的IP地址,然后再问.com域名服务器,依次类推)。

DNS欺骗的方式?

hosts文件篡改

本机DNS劫持

DNS通讯包篡改

SYN Flood:SYN-FLOOD是一种常见的DDos攻击,拒绝服务攻击。通过网络服务所在的端口发送大量伪造原地址的攻击报文,发送到服务端,造成服务端上的半开连接队列被占满,从而阻止其他用户进行访问。

它的数据报特征是大量syn包,并且缺少最后一步的ACK回复。

传输层

传输层是重头戏,其中包括两个主要协议TCP,UDP。其中TCP提供可靠的有保证的传输,涉及的知识点比较多,面试中也被问得比较多。

TCP 和 UDP 有什么区别?

最基本的是基于连接和无连接的区别,这是因为协议的目的是不一样的。TCP实现的是可靠传输,因此就需要进行拥塞控制和流量控制,超时重传,乱序分包进行重排等相关实现。而UDP是没有连接的概念,只管发送出去,也不管是否可达或者是是否可以收到回应报文。因此这就体现在TCP报文首部需要20个字节以上,而UDP报文首都需要8个字节就可以了。

TCP与UDP区别总结:

1)TCP面向连接(如打电话要先拨号建立连接); UDP是无连接的,即发送数据之前不需要建立连接

2)TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付

3)TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流; UDP是面向报文的,UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)

4)每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信

5)TCP首部开销20字节(32bit x 5); UDP的首部开销小,只有8个字节(16位源端口,16位目的端口,16位长度,16位校验和)

6)TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

TCP 和 UDP 的应用场景?

从特点上,TCP 是可靠的但传输速度慢 ,UDP 是不可靠的但传输速度快。因此在选用具体协议通信时,应该根据通信数据的要求而决定。

若通信数据完整性需让位与通信实时性,则应该选用 TCP 协议(如文件传输、重要状态的更新等);反之,则使用 UDP 协议(如视频传输、实时通信等)。

如何实现可靠的UDP?

自定义通讯协议,在应用层定义一些可靠的协议,比如检测包的顺序,重复包等问题,如果没有收到对方的ACK,重新发包。

UDP没有Delievery Garuantee,也没有顺序保证,所以如果你要求你的数据发送与接受既要高效,又要保证有序,收包确认等,你就需要在UDP协议上构建自己的协议。比如RTCP,RTP协议就是在UPD协议之上专门为H.323协议簇上的IP电话设计的一种介于传输层和应用层之间的协议。

简单来讲,要使用UDP来构建可靠的面向连接的数据传输,就要实现类似于TCP协议的超时重传,有序接受,应答确认,滑动窗口流量控制等机制,等于说要在传输层的上一层(或者直接在应用层)实现TCP协议的可靠数据传输机制,比如使用UDP数据包+序列号,UDP数据包+时间戳等方法,在服务器端进行应答确认机制,这样就会保证不可靠的UDP协议进行可靠的数据传输,不过这好像也是一个难题!

UDP中一个包的大小最大能多大?

相对于不同的系统,不同的要求,其得到的答案是不一样的。

1)局域网环境下,建议将UDP数据控制在1472字节以下。

以太网(Ethernet)数据帧的长度必须在46-1500字节之间,这是由以太网的物理特性决定的,这个1500字节被称为链路层的MTU(最大传输单元)。但这并不是指链路层的长度被限制在1500字节,其实这个MTU指的是链路层的数据区,并不包括链路层的首部和尾部的18个字节。所以,事实上这个1500字节就是网络层IP数据报的长度限制。因为IP数据报的首部为20字节,所以IP数据报的数据区长度最大为1480字节。而这个1480字节就是用来放TCP传来的TCP报文段或UDP传来的UDP数据报的。又因为UDP数据报的首部8字节,所以UDP数据报的数据区最大长度为1472字节。这个1472字节就是我们可以使用的字节数。

当我们发送的UDP数据大于1472的时候会怎样呢? 这也就是说IP数据报大于1500字节,大于MTU,这个时候发送方IP层就需要分片(fragmentation)。把数据报分成若干片,使每一片都小于MTU,而接收方IP层则需要进行数据报的重组。这样就会多做许多事情,而更严重的是, 由于UDP的特性,当某一片数据传送中丢失时,接收方无法重组数据报,将导致丢弃整个UDP数据报。 因此,在普通的局域网环境下,建议将UDP的数据控制在1472字节以下为好。

2)Internet编程时,建议将UDP数据控制在548字节以下

进行Internet编程时则不同,因为Internet上的路由器可能会将MTU设为不同的值。如果我们假定MTU为1500来发送数据,而途经的某个网络的MTU值小于1500字节,那么系统将会使用一系列的机制来调整MTU值,使数据报能够顺利到达目的地,这样就会做许多不必要的操作。鉴于Internet上的标准MTU值为576字节,所以我建议在进行Internet的UDP编程时,最好将UDP的数据长度控件在548字节以内。

下面说重头戏,TCP:

详细说明TCP状态迁移过程?

客户端:CLOSED初始态,发送SYN,进入SYN_SENT,收到SYN+ACK,发送ACK,进入ESTABLISHED状态,然后需要结束通信,发送FIN,进入FIN_WAIT1,收到服务器的ACK,进入FIN_WAIT2,收到服务器的FIN,发送ACK,进入TIME_WAIT,结束进入(回到)CLOSED状态。

服务端:CLOSED初始态,进入LISTEN状态,收到SYN,发送SYN+ACK,进入SYN_RCVD状态,收到ACK(第三次握手),进入ESTABLISHED状态,收到FIN,发送ACK,进入CLOSED_WAIT状态,等自己数据发完,发送FIN,进入LAST_ACK状态,如果成功,进入(返回)CLOSED状态。

TCP三次握手和四次挥手,以及各个状态的作用?

三次握手用于进行连接

第一次握手:建立连接时,客户端发送SYN包,例如seq = 200 ,SYN = 1 (200是随机产生的一个值,TCP规定SYN = 1的时候不能携带数据)给服务器,然后Socket进入SYN_SENT状态

第二次握手:服务器收到SYN报文段进行确认,发一个将SYN=1,ACK = 1,seq = 300,ack = 201(ack确认号为收到的序列号+1,ACK=1表示确认号有效,建立成功全程都是1,300是随机生成的)

第三次握手:客户端再进行一次确认,发一个ACK = 1,seq = 201,SYN = 0,ack = 301,ACK = 1(seq为第一次发送的seq+1,SYN从此都是0,ack为服务器确认的seq+1,ACK从此都是1)

建立成功 之后就可以相互发送数据报文了。

四次挥手用于断开连接

tcp四次挥手,由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

第一次挥手: 机1向主机2发送FIN报文段,表示关闭数据传送,并主机1进入FIN_WAIT_1状态,表示没有数据要传输了

第二次挥手:机2接受到FIN报文后进入CLOSE_WAIT状态(被动关闭),然后发送ACK确认,表示同意了主机1的关闭请求,这个时候主机1进入到FIN_WAIT_2状态,这个状态是相对来讲稍微持久一点的。

第三次挥手:机2等待主机1发送完数据,发送FIN到主机1请求关闭,主机2进入LAST_ACK状态,

第四次挥手:机1收到主机2发送的FIN后,回复ACK确认到主机2,主机1进入TIME_WAIT状态,主机2收到主机1的ACK后就关闭连接了,状态为CLOSED,主机1等待2MSL,仍然没有收到主机2的回复,说明主机2已经正常关闭了,主机1关闭连接

MSL(Maximum Segment Lifetime):报文最大生存时间,是任何报文段被丢弃前在网络内的最长时间。当主机1回复主机2的FIN后,等待(2-4分钟),即使两端的应用程序结束。

三次握手为什么不是两次或者四次?

两次太少,因为最后的客户端发往服务器的ACK至为重要,因为两次的话,B无法确定B的信息A是否能收到。

四次太多,因为服务器发送的SYN和对客户端的ACK可以合并为一个报文段发送,因为中间没有任何其他数据传输。如果四次,那么就造成了浪费,因为在三次结束之后,就已经可以保证A可以给B发信息,A可以收到B的信息; B可以给A发信息,B可以收到A的信息。

2MSL是什么状态?作用是什么?

是TIME_WAIT,主要有两个作用:

1)保留端口不被复用,以接受服务器可能重传的FIN。如果不这样做,那么客户端收到重发的FIN会返回一个RST报文段,而服务器期待的是正常的ACK,所以会报错。

2)保证双向的包都在网络中消失。如果不这样做,在此端口立马启动另一个相同/相似的连接,则他们可能会收到之前连接的报文段,显然不好,2MSL就能保证之前的连接的所有报文段都在网络中消失。

time_wait,close_wait状态产生的原因,keepalive?

TCP协议规定,对于已经建立的连接,网络双方要进行四次握手才能成功断开连接,如果缺少了其中某个步骤,将会使连接处于假死状态,连接本身占用的资源不会被释放。网络服务器程序要同时管理大量连接,所以很有必要保证无用连接完全断开,否则大量僵死的连接会浪费许多服务器资源。在众多TCP状态中,最值得注意的状态有两个:CLOSE_WAIT和TIME_WAIT。

CLOSE_WAIT 是被动关闭连接时形成的。根据TCP状态机,服务器端收到客户端发送的FIN,则按照TCP实现发送ACK,因此进入CLOSE_WAIT状态。但如果服务器端不执行close(),就不能由CLOSE_WAIT迁移到LAST_ACK,则系统中会存在很多CLOSE_WAIT状态的连接。此时,可能是系统忙于处理读、写操作,而未将已收到FIN的连接,进行close。此时,recv/read已收到FIN的连接socket,会返回0。

解决CLOSE_WAIT的方法:

1 一般原因都是TCP连接没有调用关闭方法。需要应用来处理网络链接关闭。

2 对于Web请求出现这个原因,经常是因为Response的BodyStream没有调用Close。

3 TCP的KeepLive功能,可以让操作系统替我们自动清理掉CLOSE_WAIT的连接。但是KeepLive在Windows操作系统下默认是7200秒,也就是2个小时才清理一次。往往满足不了要求。可以调小该数值。

close_Wait引发的问题: close_Wait会占用一个连接,网络可用连接小。数量过多,可能会引起网络性能下降,并占用系统非换页内存。尤其是在有连接池的情况下(比如HttpRequest)会耗尽连接池的网络连接数,导致无法建立新的网络连接。

大量TIME_WAIT存在什么问题,如何解决?

ip_local_port_range范围不到3w,大量的TIME_WAIT状态使得local port在TIME_WAIT持续期间不能被再次分配,即没有可用的local port,这将是导致新建连接失败的最大原因。

解决方案:

1)修改系统配置

具体来说,需要修改本文前面介绍的tcp_max_tw_buckets、tcp_tw_recycle、tcp_tw_reuse这三个配置项。

2)修改应用程序

具体来说,可以细分为两种方式:

1/ 将TCP短连接改造为长连接。通常情况下,如果发起连接的目标也是自己可控制的服务器时,它们自己的TCP通信最好采用长连接,避免大量TCP短连接每次建立/释放产生的各种开销;如果建立连接的目标是不受自己控制的机器时,能否使用长连接就需要考虑对方机器是否支持长连接方式了。

2/ 通过getsockopt/setsockoptapi设置socket的SO_LINGER选项

3/ 服务器可以设置SO_REUSEADDR套接字选项来通知内核,如果端口忙,但TCP连接位于TIME_WAIT状态时可以重用端口。在一个非常有用的场景就是,如果你的服务器程序停止后想立即重启,而新的套接字依旧希望使用同一端口,此时SO_REUSEADDR选项就可以避免TIME_WAIT状态。

TCP重传机制?

TCP是一种可靠的协议,在网络交互的过程中,由于TCP报文是封装在IP协议中的,IP协议的无连接特性导致其可能在交互的过程中丢失,在这种情况下,TCP协议如何保障其传输的可靠性呢?依靠确认/重传机制。

重传又分为超时重传和快速重传。

1)超时重传

说白了就是在请求包发出去的时候,开启一个计时器,当计时器达到时间之后,没有收到ACK,则就进行重发请求的操作,一直重发直到达到重发上限次数或者收到ACK。发送端的等待的时间叫RTO(Retransmission TimeOut).

快速重传

2)还有一种机制就是快速重传,Fast Retransmit是由接收端主动要求重发的,当接收方收到的数据包是不正常的序列号,那么接收方会重复把应该收到的那一条ACK重复发送,这个时候,如果发送方收到连续3条的同一个序列号的ACK,那么就会启动快速重传机制,把这个ACK对应的发送包重新发送一次。

TCP拥塞控制?

TCP 的拥塞控制方法主要有四种:慢开始、拥塞避免、快重传和快恢复。

为了简化问题,在下面的讨论中,我们作出如下两个假设:

a 数据单向传输;

b 接收方的缓存是无限大的,窗口大小仅由网络的拥塞程度决定;

(1) 慢开始和拥塞避免

这里存在这样一个原则:只要网络没有出现拥塞,拥塞窗口 cwnd(可以理解为发送窗口)就可以无限增大,以便于单次发送更多的数据,但是只要网络发生了拥塞,就必须把拥塞窗口减小,以减少涌入网络的数据量,从而减轻网络的拥塞程度。

但是发送方如何知道网络发生了拥塞呢?当网络发生拥塞时,路由器的缓存便处于爆满状态,此时它不得不丢弃一部分分组。这样发送方就不可能收到确认报文,最终导致等待超时。现代网络线路的传输质量都很好,因为硬件层面的问题导致丢弃分组的情况是很少发生的。也就是说,出现超时便代表着网络出现了拥塞。

本来是通过控制拥塞窗口的大小来实现 TCP 的拥塞控制,但是为了更好地解释慢开始的原理,我们将报文段的个数作为拥塞窗口的单位,即从原来的增加窗口大小变为了增加报文段的个数。这样可以用较小的数字来说明拥塞控制的原理。

慢开始算法的“慢”不是指增长慢,而是指最开始的时候,从一个较低的起点开始增长。

值得注意的是,上面的结论并不具有实际意义,因为拥塞窗口只要收到一个新的确认报文就会增大(假如这个确认报文段使得窗口增大),并且立即发送新窗口中的数据,而不必等到该轮次中所有的报文段都成功确认。

同时为了避免拥塞窗口无限增大造成网络拥塞,需要设置一个慢开始门限 ssthresh。拥塞窗口 cwnd 的大小和慢开始门限 ssthresh 之间存在如下的关系:

a 当 cwnd < ssthresh 时,使用慢开始算法;

b 当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法;

在慢开始阶段,拥塞窗口的大小呈指数增加;

到达慢开始门限后,采用拥塞避免算法,窗口大小依次加 1,呈线性增长趋势;

当窗口 cwnd = 24 时,出现了超时,此时发送方判断网络发生了阻塞,于是调整 ssthresh = cwnd/2 = 12,同时重新设置窗口 cwnd = 1;

接下来继续慢开始算法,达到新的门限 ssthresh = 12 时改用拥塞避免算法,窗口值呈线性增大;

当窗口值 cwnd = 16 时,出现了新的情况:发送方连续收到了 3 个对于同一报文段的重复确认(图中的 3-ACK),这个问题将在快重传和快恢复中继续讨论;

(3) 快重传和快恢复

我们先考虑这样一种情况:有时候,确认报文段只是在网络传输中丢失了,但是其实网络并没有发生拥塞。由于发送方接收不到确认报文段而导致超时的发生,此时便会开启慢开始算法,然后将窗口置为 1,导致传输效率降低。

在下面的图中,发送方先发送了 M1 和 M2,并且成功收到了它们的确认报文段,但是接下来发送的 M3 却丢失了。由于接受方此时并不知道发送方向其发送了 M3,所以此时它做出任何响应。当接受方接收到发送方继续发送的 M4 的时候,经过的简单对比,它知道 M3 肯定是丢失了,于是立刻向发送方发出对 M2 的重复确认,对于后面的 M5、M6 也是如此。于是接收方一共收到了 4 个对 M2 的确认,除去第一个之外,后面的三个都是重复确认,也即图中的 3-ACK。此时,快重传算法规定,当发送方连续收到 3 个重复确认的时候,就必须立即对丢失的报文段进行重传(即快重传),这样便不会导致超时的发生,从而避免了之前的情况。

接下来对于图中的 3-ACK 点来说,发送方知道只是丢失了部分报文段,于是执行快恢复算法,调整 ssthresh = cwnd/2 = 8,同时设置 cwnd = ssthresh = 8,然后接着开始执行拥塞避免算法。

另外,我们在刚开始的时候,假定发送窗口的大小只会受到网络的影响。但是接收方的缓存肯定是有限的,也就是说:接收窗口 rwnd 和拥塞窗口 cwnd 二者共同制约着发送窗口的大小。显然,三者之间存在下图中的关系:

发送窗口上限 = Min[rwnd, cwnd]

上述公式说明,每次对发送窗口进行调整时,需要根据当前的网络状况和接收窗口的大小而定。

TCP的滑动窗口?

滑动窗口是发送方通过接受方的确认报文段中描述的缓冲区的大小来计算自己最多能发送多长的数据。如果发送方收到接受方的窗口大小为0的TCP数据报,那么发送方将停止发送数据,等到接受方发送窗口大小不为0的数据报的到来。

缓存与滑动窗口的关系

我们在上面的例子中所提到的字节流实际上是位于发、接双方的缓存中的,窗口在字节流上滑动,对发送和接收的字节流进行控制。

在发送方这边,发送窗口后沿的字节会被删去,应用进程写入的新的字节又会添加到字节流的最前头。因此必须对应用程序写入字节的速度进行控制,否则会爆缓存。

在接收方这边,接收窗口后沿的数据只是在确认报文段中已经确认的数据,等待被应用进程读取,成功读取后才能删除。如果应用进程来不及读取,接收缓存就会被填满,最终导致接收窗口为 0,然后又会反馈到发送窗口那边,使发送停止。

值得说明的是,在上面的例子中,我们为了解释的方便,只考虑了一方发送、一方接收的情况。但是由于 TCP 是全双工通信,实际中任意一方都是发送窗口与接收窗口并存的。

TCP精髓问题:停止等待协议、连续ARQ协议

停止等待协议

停止等待协议是tcp保证传输可靠的重要途径,”停止等待”就是指发送完一个分组就停止发送,等待对方的确认,只有对方确认过,才发送下一个分组.

停止等待协议的优点是简单,但是缺点是信道的利用率太低。

连续ARQ协议

连续重发请求ARQ方案是指发送方可以连续发送一系列信息帧,即不用等前一帧被确认便可继续发送下一帧,效率大大提高。但在这种重发请求方案中,需要在发送方设置一个较大的缓冲存储空间(称作重发表),用以存放若干待确认的以及待发送信息帧。当发送方收到对某信息帧的确认帧后,便可从重发表中将该信息帧删除。所以,连续重发请求ARQ方案的链路传输效率大大提高,但相应地需要更大的缓冲存储空间。

在这一协议中,当发送站点发送完一个数据帧后,不是停下来等待应答帧,而是可以连续再发送若干个数据帧。如果在此过程中又收到了接收端发来的应答帧,那么还可以接着发送数据帧。由于减少了等待时间,整个通信的吞吐量就提高了。

ARQ代表的是自动重传请求(Auto Repeat reQuest,ARQ),而GBN与选择重传都属于其中。其中GBN的发送窗口>1,接收窗口=1,选择重传协议:发送窗口大小>1,接收窗口大于1。GBN协议中接收方可以发送累计确认帧ACK,而选择重传没有累计确认的特点。

说说Nagle算法?

背景:如果互联网上传递的都是小包,那绝对是个灾难,每个网络请求都耗费比较大的资源,如果一份数据分为零零散散很多份小包,每个网络传输都只传输一个小包,那么是典型的浪费资源,增加拥堵。

Nagle算法的基本定义是任意时刻,最多只能有一个未被确认的小段。 所谓“小段”,指的是小于MSS尺寸的数据块,所谓“未被确认”,是指一个数据块发送出去后,没有收到对方发送的ACK确认该数据已收到。

Nagle算法规定了,发送方网络链路上一个连接只能有一个未获得ACK的请求包。这个就意味着,发送方只有等待上一个请求的ACK回来之后才能发送下一个请求,这样两个请求过程中间,发送方的缓存区就存储了足够滑动窗口大小的包进行传递,这样就有效避免了大量的小包产生。

Keepalive是什么东西,如何使用?

keepalive,是在TCP中一个可以检测死连接的机制。

keepalive 原理很简单,TCP会在空闲了一定时间后发送数据给对方:

1.如果主机可达,对方就会响应ACK应答,就认为是存活的。

2.如果可达,但应用程序退出,对方就发FIN应答,发送TCP撤消连接。

3.如果可达,但应用程序崩溃,对方就发RST消息。

4.如果对方主机不响应ack, rst,继续发送直到超时,就撤消连接。这个时间就是默认的二个小时。

Keepalive 和 应用层的 HeartBeat 的联系和区别?

Keepalive适用于清除死亡时间比较长的连接。

1)默认不开启,采用keepalive,它会先要求此连接一定时间没有活动(一般是几个小时),然后发出数据段,经过多次尝试后(每次尝试之间也有时间间隔),如果仍没有响应,则判断连接中断。可想而知,整个周期需要很长的时间(默认时长是2小时)。

2)keepalive只能检测连接是否存活,不能检测连接是否可用。比如服务器因为负载过高导致无法响应请求但是双方的连接仍然存在,此时keepalive无法判断该连接是否可用。

3)如果TCP连接中的另一方因为停电突然断网等非正常断开的现象,由于服务器端(被动连接/断开的一方)并不知道客户端已断开连接,此时若服务器正在发送数据,那么会导致数据发送失败并进行数据重传,由于重传包的优先级要高于keepalive的数据包,因此keepalive的数据包无法及时发送出去。

所以,需要一种方法能够清除和回收那些在系统不知情的情况下死去了很久的连接,keepalive是非常好的选择。

在大部分情况下,特别是分布式环境中,我们需要的是一个能够 快速或者实时监控连接状态的机制 ,这里,heart-beat才是更加合适的方案。

它们的不同点在于,keepalive是tcp实现中内建的机制,是在创建tcp连接时通过设置参数启动keepalive机制;而heart-beat则需要在tcp之上的应用层实现。一个简单的heart-beat实现一般测试连接是否中断采用的时间间隔都比较短,可以很快的决定连接是否中断。并且,由于是在应用层实现,因为可以自行决定当判断连接中断后应该采取的行为,而keepalive在判断连接失败后只会将连接丢弃。

TCP中已有SO_KEEPALIVE选项,为什么还要在应用层加入心跳包机制,或者说,光用keepalive够么?

主要是因为TCP协议中的SO_KEEPALIVE有几个致命的缺陷:

1、keepalive只能检测连接是否存活,不能检测连接是否可用。比如服务器因为负载过高导致无法响应请求但是双方的连接仍然存在,此时keepalive无法判断该连接是否可用。

2、如果TCP连接中的另一方因为停电突然断网等非正常断开的现象,由于服务器端(被动连接/断开的一方)并不知道客户端已断开连接,此时若服务器正在发送数据,那么会导致数据发送失败并进行数据重传,由于重传包的优先级要高于keepalive的数据包,因此keepalive的数据包无法及时发送出去。

3、当重传超过一定次数,TCP协议会发送keepalive探测包到客户端,一旦探测包没有返回,服务器端会以keepaliveinterval的频率继续发送探测包,经过若干次重试,若服务器一直没有收到应答就会认为该TCP连接已经断开(默认时长是2小时),而2小时以内这个连接一直不会断开,浪费系统资源。

什么是TCP的自连接,如何解决?

TCP自连接,就是出现源ip和源端口通目的ip和目的端口完全相同的情况。

解决之道:

发表评论

后发表评论