问题整理自cyc大佬的专栏

推荐付费阅读他的其他文章,很有收获。另外大佬的GitHub内容也非常有用。

部分答案整理自网络,点击蓝字可以查看原链接。蓝字都是可以点进去的。

上一篇整理了操作系统及Linux的基本问题,接下来整理计算机网络的有关知识。


一 网络基础

1 ★★★ 各层协议的作用,以及 TCP/IP 协议的特点。

OSI参考模型与TCP/IP模型

OSI参考模型中最靠近用户的一层,是为计算机用户提供应用接口,也为用户直接提供各种网络服务。我们常见应用层的网络服务协议有:HTTP,HTTPS,FTP,POP3、SMTP等。

表示层提供各种用于应用层数据的编码和转换功能,确保一个系统的应用层发送的数据能被另一个系统的应用层识别。如果必要,该层可提供一种标准表示形式,用于将计算机内部的多种数据格式转换成通信中采用的标准表示形式。数据压缩和加密也是表示层可提供的转换功能之一。

会话层就是负责建立、管理和终止表示层实体之间的通信会话。该层的通信由不同设备中的应用程序之间的服务请求和响应组成。   

传输层建立了主机端到端的链接,传输层的作用是为上层协议提供端到端的可靠和透明的数据传输服务,包括处理差错控制和流量控制等问题。该层向高层屏蔽了下层数据通信的细节,使高层用户看到的只是在两个传输实体间的一条主机到主机的、可由用户控制和设定的、可靠的数据通路。我们通常说的,TCP UDP就是在这一层。端口号既是这里的“端”。   

网络层通过IP寻址来建立两个节点之间的连接,为源端的运输层送来的分组,选择合适的路由和交换节点,正确无误地按照地址传送给目的端的运输层。就是通常说的IP层。这一层就是我们经常说的IP协议层。IP协议是Internet的基础。

数据链路层  将比特组合成字节,再将字节组合成帧,使用链路层地址 (以太网使用MAC地址)来访问介质,并进行差错检测。数据链路层又分为2个子层:逻辑链路控制子层(LLC)和媒体访问控制子层(MAC)。MAC子层处理CSMA/CD算法、数据出错校验、成帧等;LLC子层定义了一些字段使上次协议能共享数据链路层。 在实际使用中,LLC子层并非必需的。

物理层通过物理介质传输比特流。规定了电平、速度和电缆针脚。常用设备有(各种物理设备)集线器、中继器、调制解调器、网线、双绞线、同轴电缆。这些都是物理层的传输介质。

而OSI对应的TCP/IP五层模型为:

 

 

 TCP/IP 是一类协议系统,它是用于网络通信的一套协议集合

 也可分为四层,为:

 

 

2 ★★☆ 以太网的特点,以及帧结构。

以太网是目前最流行的有线的局域网技术.以太网的数据帧格式如下图所示:

在以太网链路上的数据包称作以太帧。以太帧起始部分由前导码和帧开始符组成。后面紧跟着一个以太网报头,以MAC地址说明目的地址源地址。帧的中部是该帧负载的包含其他协议报头的数据包(例如IP协议)。以太帧由一个32位冗余校验码结尾。它用于检验数据传输是否出现损坏

各个字段的作用:

  • 前同步码:第一个字段是7个字节的前同步码,1和0交替,作用是用来使接收端的适配器在接收MAC帧时能够迅速调整时钟频率,使它和发送端的频率相同。
  • 帧开始定界符:第二个字段是1个字节的帧开始定界符,前六位1和0交替,最后的两个连续1表示告诉接收端适配器:“帧信息要来了,你准备接收把。
  • MAC 目的地址:第三个字段是6字节(MAC地址占48位,如:FF,FF,FF,FF,FF),发送方的网卡(MAC)地址,用处是当网卡接收到一个数据帧时,首先会检查该帧的目的地址,是否与当前适配器的物理地址相同,如果相同则会进一步处理,不同则直接丢弃。
  • 源MAC地址:发送端的MAC地址同样占6个字节。
  • 类型:该字段在网络协议栈分解中及其重要,考虑当PDU(协议数据单元)来到某一层时,它需要将PDU交付给上层,而上层协议众多,所以在处理数据的时候,必须要一个字段标识我这个交付给谁。如,该字段为0x0800时,表示将有效载荷交付给IP协议,为0x0806交付给ARP,0X8035交付给RARP。
  • 数据:数据也叫有效载荷,除过当前层协议需要使用的字段外,即需要交付给上层的数据,以太网帧数据长度规定最小为46字节,最大为1500字节,如果有不到46字节时,会用填充字节填充到最小长度。最大值也叫最大传输单元(MTU),我们可以再 Linux输入 ifconfig 可以看到有一项MTU:1500。
  • 帧检验序列FCS(使用CRC校验法):检测该帧是否出现差错。

3 ★★☆ 集线器、交换机、路由器的作用,以及所属的网络层。

路由器:(Router)是连接因特网中各局域网、广域网的设备。在路由器中记录着路由表,它会根据信道的情况自动选择和设定路由,以最佳路径,按前后顺序发送信号。发生在网络层。 
交换机:(Switch)是一种用于电(光)信号转发的网络设备。它可以为接入交换机的任意两个网络节点提供独享的电信号通路,把传输的信息送到符合要求的相应路由上。发生在数据链路层。 
集线器:(Hub)是指将多条以太网双绞线或光纤集合连接在同一段物理介质下的设备。发生在物理层。

路由器 交换机
工作层次 网络层 数据链路层
转发依据 IP地址 Mac地址
功能 连接不同的网络 连接局域网中的电脑
宽带影响 共享宽带 独享宽带

简单的说路由器专管入网,交换机只管配送,路由就是给你找路让你上网的,交换机只负责开门,交换机上面要没有路由你是上不了网的。 

交换机 集线器
工作层次 数据链路层 物理层
宽带影响 独享 共享
数据传输 有目的发送 广播发送
传输模式 全双工或半双工 半双工

集线器工作的时候,如果局域网中的一台电脑要发送消息,则局域网内的所有电脑都可以接收到这个消息。安全性较差,而且每一次只能有一个发送,只有这个发送完毕其他电脑才能再发送,这称为半双工模式。而交换机有“记忆功能”,它能根据相应的MAC地址直接有目的的发送到目标电脑。但是如果向一台新的电脑发送消息,那么传输方式也将是广播,只有找到这台电脑, 并记住它的MAC地址后,以后才能直接发送给它。通过交换机连接的电脑可以同时发送消息互不影响,就像我们平时打电话一样,这称为全双工模式,传输速率比集线器大大提高。 

4 ★★☆ IP 数据数据报常见字段的作用。

(一)IP协议的功能:

(1)寻址和路由;(根据对方的IP地址,寻找最佳路径传输信息);

(2)传递服务:① 不可靠(IP协议只是尽自己最大努力去传输数据包),可靠性由上层协议提供(TCP协议);② 无连接;(事先不建立会话);

(3)数据包的分片和重组。

字段:

 图中前20字节(有的IP数据报有特殊选项另算字节数)被称作IP数据报首部。

4位版本字段:目前版本IPv4,故版本号为4;

4位首部长度字段:指IP数据报首部长度(以字为单位),例如无选项字段,则取20;

8位服务类型字段(TOS):从左至右依次是 3bit优先权字段(现已被舍弃) 1bit最小延时 1bit最大吞吐量 1bit最高可靠性 1bit最小费用  1bit未用(置0)中间这4个位只能选其一或者都不选,不选意味着是一般服务;

16位总长度字段(字节数):IP数据报长度,也就是数据报首部和数据内容的字节数,利用首部长度字段和总长度字段就可以知道IP数据报重数据内容的起始位置和长度;

16位标识字段:通常没发送一份报文加1;

标识和偏移字段:在讨论分片是使用;

8位生存时间字段(Time to life):由源主机设置(通常为32或者64),一旦经过一个处理它的路由器就减一,若减到零数据报丢弃;

8位协议字段:根据他可以知道是哪个协议向它传递数据,当目的主机收到以太网数据帧是,数据就开始从协议栈中由底向上升,

同时去掉各层协议加上的报文首部。每层协议盒都要去检查报文首部中的协议标识,以确定接受数据的上层协议。这个过程叫做分用。

16位首部校验和

32位的源、目的地址:IP地址而已;

5 ★☆☆ ARP 协议的作用,以及维护 ARP 缓存的过程。

ARP 协议具有两项基本功能:

将 IPv4 地址解析为 MAC 地址

维护映射的缓存

需要能够将逻辑地址和相应的物理地址之间进行映射,完成这样的映射可以使用静态映射和动态映射。

静态映射:创建一个表,存储逻辑地址和物理地址之间的关联关系。然后将网络上的每个主机都存储这张表。缺点是映射表必须周期的更新,增加了 网络的开销。

动态地址映射,地址解析协议ARP和逆地址解析协议RARP。

地址解析协议ARP(Address Resolution Protocol),负责完成逻辑地址向物理地址的动态映射,将32位逻辑地址(IP地址)转换为48位的物理地址(MAC地址)。
ARP是通过一个查找表(ARP缓存)来执行这种转换的。当在ARP缓存中没有找到地址时,则向网络发送一个广播请求,网络上所有的主机和路由器都接收和处理这个ARP请求,但是只有相同IP地址的接收到广播请求的主机或路由器,发回一个ARP应答分组,应答中包含它的IP地址和物理地址,并保存在请求主机的ARP缓存中。其他主机或路由器都丢弃此分组。

6 ★★☆ ICMP 报文种类以及作用;和 IP 数据报的关系;Ping 和 Traceroute 的具体原理。

ICMP(Internet Control Message Protocol)因特网控制报文协议。它是IPv4协议族中的一个子协议,用于IP主机、路由器之间传递控制消息。控制消息是在网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然不传输用户数据,但是对于用户数据的传递起着重要的作用。 
ICMP协议与ARP协议不同,ICMP靠IP协议来完成任务,所以ICMP报文中要封装IP头部。它与传输层协议(如TCP和UDP)的目的不同,一般不用来在端系统之间传送数据,不被用户网络程序直接使用,除了想Ping和Tracert这样的诊断程序。

MP报告无法传送的数据报的错误,并帮助对这些错误进行疑难解答。例如,如果IPv4不能讲数据报传送到目标主机,则路由器上的或目标主机上的ICMP会向主机发送一条“无法到达目标”消息。CMP协议只是试图报告错误,并对特定的情况提供反馈,但最终并没有使IPv4成为一个可靠的协议。ICMP消息是以未确认的IPv4数据报传送的,它们自己也不可靠。

常见类型:

CMP类型报文总的来说分为2类:

(1)差错报告报文

类型值为3时:表示终点不可达

类型值为4时:表示源点抑制

类型值为5时:表示改变路由(Redirect)

类型值为11时:表示超时

类型值为12时:表示参数问题

(2)询问报文

类型值为8或者0时:表示回送(Echo)请求或应答

类型值为13或14时:表示时间戳(Timestamp)请求或应答

ping命令工作原理

ping命令主要是用于检测网络的连通性。

Ping命令发送一个ICMP请求报文给目的IP,然后目的IP回复一个ICMP报文。

原理:网络上的机器都有唯一确定的IP地址,我们给目标IP地址发送一个数据包,对方就要返回一个同样大小的数据包,根据返回的数据包我们可以确定目标主机的存在,可以初步判断目标主机的操作系统等。

因为ping命令是使用ICMP协议,所以没有端口号,但是有两个域:类型和代码。

traceroute工作原理

traceroute是利用ICMP及IP头部的TTL。首先,traceroute送出一个TTL是1的IP数据包(其实,每次送出的为3个40字节的包,包括源地址,目的地址和包发出的时间标签)到目的地,当路径上的第一个路由器收到IP数据包时,将TTL减1。此时,TTL变为0,所以将该路由器会将此IP数据包丢掉,并返回一个ICMP数据包(包括发IP包的源地址,IP包的所有内容及路由器的IP地址),当traceroute收到这个消息后,接着继续发生TTL为2的IP数据包给第二个路由器。以此类推,直到IP数据包达到最后一台路由器时,会返回一个ICMP echo reply的数据包。

7 ★★★ UDP 与 TCP 比较,分析上层协议应该使用 UDP 还是 TCP

TCP和UDP区别

 

 

TCP

UDP

是否连接

面向连接

面向非连接

传输可靠性

可靠的

不可靠的

应用场合

传输大量的数据

少量数据

速度

 

 OSI 和 TCP/IP 模型在传输层定义两种传输协议:TCP(或传输控制协议)和 UDP(或用户数据报协议)。

UDP 
    UDP 与 TCP 的主要区别在于 UDP 不一定提供可靠的数据传输。事实上,该协议不能保证数据准确无误地到达目的地。UDP 在许多方面非常有效。当某个程序的目标是尽快地传输尽可能多的信息时(其中任意给定数据的重要性相对较低),可使用 UDP。ICQ 短消息使用 UDP 协议发送消息。 
    许多程序将使用单独的TCP连接和单独的UDP连接。重要的状态信息随可靠的TCP连接发送,而主数据流通过UDP发送。

TCP
    TCP的目的是提供可靠的数据传输,并在相互进行通信的设备或服务之间保持一个虚拟连接。TCP在数据包接收无序、丢失或在交付期间被破坏时,负责数据恢复。它通过为其发送的每个数据包提供一个序号来完成此恢复。记住,较低的网络层会将每个数据包视为一个独立的单元,因此,数据包可以沿完全不同的路径发送,即使它们都是同一消息的组成部分。这种路由与网络层处理分段和重新组装数据包的方式非常相似,只是级别更高而已。
    为确保正确地接收数据,TCP要求在目标计算机成功收到数据时发回一个确认(即 ACK)。如果在某个时限内未收到相应的 ACK,将重新传送数据包。如果网络拥塞,这种重新传送将导致发送的数据包重复。但是,接收计算机可使用数据包的序号来确定它是否为重复数据包,并在必要时丢弃它。

TCP与UDP的选择

    如果比较UDP包和TCP包的结构,很明显UDP包不具备TCP包复杂的可靠性与控制机制。与TCP协议相同,UDP的源端口数和目的端口数也都支持一台主机上的多个应用。一个16位的UDP包包含了一个字节长的头部和数据的长度,校验码域使其可以进行整体校验。(许多应用只支持UDP,如:多媒体数据流,不产生任何额外的数据,即使知道有破坏的包也不进行重发。) 
    很明显,当数据传输的性能必须让位于数据传输的完整性、可控制性和可靠性时,TCP协议是当然的选择。当强调传输性能而不是传输的完整性时,如:音频和多媒体应用,UDP是最好的选择。在数据传输时间很短,以至于此前的连接过程成为整个流量主体的情况下,UDP也是一个好的选择,如:DNS交换。把SNMP建立在UDP上的部分原因是设计者认为当发生网络阻塞时,UDP较低的开销使其有更好的机会去传送管理数据。TCP丰富的功能有时会导致不可预料的性能低下,但是我们相信在不远的将来,TCP可靠的点对点连接将会用于绝大多数的网络应用。

TCP协议和UDP协议特性区别总结:

     1. TCP协议在传送数据段的时候要给段标号;UDP协议不

     2. TCP协议可靠;UDP协议不可靠

     3. TCP协议是面向连接;UDP协议采用无连接

     4. TCP协议负载较高,采用虚电路;UDP采用无连接

     5. TCP协议的发送方要确认接收方是否收到数据段(3次握手协议)

     6. TCP协议采用窗口技术和流控制

QQ既有UDP也有TCP!
不管UDP还是TCP,最终登陆成功之后,QQ都会有一个TCP连接来保持在线状态。这个TCP连接的远程端口一般是80,采用UDP方式登陆的时候,端口是8000。

UDP协议是无连接方式的协议,它的效率高,速度快,占资源少,但是其传输机制为不可靠传送,必须依靠辅助的算法来完成传输控制。QQ采用的通信协议以UDP为主,辅以TCP协议。由于QQ的服务器设计容量是海量级的应用,一台服务器要同时容纳十几万的并发连接,因此服务器端只有采用UDP协议与客户端进行通讯才能保证这种超大规模的服务。

  QQ客户端之间的消息传送也采用了UDP模式,因为国内的网络环境非常复杂,而且很多用户采用的方式是通过代理服务器共享一条线路上网的方式,在这些复杂的情况下,客户端之间能彼此建立起来TCP连接的概率较小,严重影响传送信息的效率。而UDP包能够穿透大部分的代理服务器,因此QQ选择了UDP作为客户之间的主要通信协议。
  采用UDP协议,通过服务器中转方式。因此,现在的IP侦探在你仅仅跟对方发送聊天消息的时候是无法获取到IP的。大家都知道,UDP 协议是不可靠协议,它只管发送,不管对方是否收到的,但它的传输很高效。但是,作为聊天软件,怎么可以采用这样的不可靠方式来传输消息呢?于是,腾讯采用了上层协议来保证可靠传输:如果客户端使用UDP协议发出消息后,服务器收到该包,需要使用UDP协议发回一个应答包。如此来保证消息可以无遗漏传输。之所以会发生在客户端明明看到“消息发送失败”但对方又收到了这个消息的情况,就是因为客户端发出的消息服务器已经收到并转发成功,但客户端由于网络原因没有收到服务器的应答包引起的。

8 ★★★ 理解三次握手以及四次挥手具体过程,三次握手的原因、四次挥手原因、TIME_WAIT 的作用

 建立连接的过程:

第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
 

1)客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
2)服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
3)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
4)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
6)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
--------------------- 

常见问题:

【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

【问题3】为什么不能用两次握手进行连接?

答:3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。

       现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。

【问题4】如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

9  ★★★ 可靠传输原理,并设计可靠 UDP 协议。

 TCP的可靠性传输:确认机制、重传机制、滑动窗口。

1)首先,采用三次握手来建立TCP连接,四次握手来释放TCP连接,从而保证建立的传输信道是可靠的。

(2)其次,TCP采用了连续ARQ协议(回退N,Go-back-N;超时自动重传)来保证数据传输的正确性,使用滑动窗口协议来保证接方能够及时处理所接收到的数据,进行流量控制。

(3)最后,TCP使用慢开始、拥塞避免、快重传和快恢复来进行拥塞控制,避免网络拥塞。

UDP不属于连接协议,具有资源消耗少,处理速度快的优点,所以通常音频,视频和普通数据在传送时,使用UDP较多,因为即使丢失少量的包,也不会对接受结果产生较大的影响。

传输层无法保证数据的可靠传输,只能通过应用层来实现了。实现的方式可以参照tcp可靠性传输的方式,只是实现不在传输层,实现转移到了应用层。

最简单的方式是在应用层模仿传输层TCP的可靠性传输。下面不考虑拥塞处理,可靠UDP的简单设计。

  • 1、添加seq/ack机制,确保数据发送到对端
  • 2、添加发送和接收缓冲区,主要是用户超时重传。
  • 3、添加超时重传机制。

详细说明:送端发送数据时,生成一个随机seq=x,然后每一片按照数据大小分配seq。数据到达接收端后接收端放入缓存,并发送一个ack=x的包,表示对方已经收到了数据。发送端收到了ack包后,删除缓冲区对应的数据。时间到后,定时任务检查是否需要重传数据。

目前有如下开源程序利用udp实现了可靠的数据传输。分别为RUDP、RTP、UDT

开源程序

1、RUDP(Reliable User Datagram Protocol)

RUDP 提供一组数据服务质量增强机制,如拥塞控制的改进、重发机制及淡化服务器算法等,从而在包丢失和网络拥塞的情况下, RTP 客户机(实时位置)面前呈现的就是一个高质量的 RTP 流。在不干扰协议的实时特性的同时,可靠 UDP 的拥塞控制机制允许 TCP 方式下的流控制行为。

2、RTP(Real Time Protocol)

RTP为数据提供了具有实时特征的端对端传送服务,如在组播或单播网络服务下的交互式视频音频或模拟数据。

应用程序通常在 UDP 上运行 RTP 以便使用其多路结点和校验服务;这两种协议都提供了传输层协议的功能。但是 RTP 可以与其它适合的底层网络或传输协议一起使用。如果底层网络提供组播方式,那么 RTP 可以使用该组播表传输数据到多个目的地。

RTP 本身并没有提供按时发送机制或其它服务质量(QoS)保证,它依赖于底层服务去实现这一过程。 RTP 并不保证传送或防止无序传送,也不确定底层网络的可靠性。 RTP 实行有序传送, RTP 中的序列号允许接收方重组发送方的包序列,同时序列号也能用于决定适当的包位置,例如:在视频解码中,就不需要顺序解码。

3、UDT(UDP-based Data Transfer Protocol)

基于UDP的数据传输协议(UDP-basedData Transfer Protocol,简称UDT)是一种互联网数据传输协议。UDT的主要目的是支持高速广域网上的海量数据传输,而互联网上的标准数据传输协议TCP在高带宽长距离网络上性能很差。

顾名思义,UDT建于UDP之上,并引入新的拥塞控制和数据可靠性控制机制。UDT是面向连接的双向的应用层协议。它同时支持可靠的数据流传输和部分可靠的数据报传输。由于UDT完全在UDP上实现,它也可以应用在除了高速数据传输之外的其它应用领域,例如点到点技术(P2P),防火墙穿透,多媒体数据传输等等。

10 ★★☆ TCP 拥塞控制的作用,理解具体原理。

计算机网络中的带宽、交换结点中的缓存和处理机等,都是网络的资源。在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就会变坏。这种情况就叫做拥塞。

拥塞控制就是防止过多的数据注入网络中,这样可以使网络中的路由器或链路不致过载。拥塞控制是一个全局性的过程,和流量控制不同,流量控制指点对点通信量的控制。
慢开始算法:

 发送方维持一个叫做拥塞窗口cwnd(congestion window)的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口,另外考虑到接受方的接收能力,发送窗口可能小于拥塞窗口。

慢开始算法的思路就是,不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小。

 快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认。快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。

为避免发生网路中的全局同步现象,路由器采用随机早期检测,

  使路由器的队列维持两个参数,即队列长队最小门限min和最大门限max,每当一个分组到达的时候,RED就计算平均队列长度。然后分情况对待到来的分组:

①平均队列长度小于最小门限——把新到达的分组放入队列排队。

②平均队列长度在最小门限与最大门限之间——则按照某一概率将分组丢弃。

③平均队列长度大于最大门限——丢弃新到达的分组。

以概率p随机丢弃分组,让拥塞控制只在个别的TCP连接上执行,因而避免全局性的拥塞控制。

       RED的关键就是选择三个参数最小门限、最大门限、丢弃概率和计算平均队列长度。平均队列长度采用加权平均的方法计算平均队列长度,这和往返时间(RTT)的计算策略是一样的。

11 ★★☆ DNS 的端口号;TCP 还是 UDP作为缓存、负载均衡。

DNS同时占用UDP和TCP端口53是公认的,这种单个应用协议同时使用两种传输协议的情况在TCP/IP栈也算是个另类。但很少有人知道DNS分别在什么情况下使用这两种协议。 DNS在进行区域传输的时候使用TCP协议,其它时候则使用UDP协议; 
    DNS的规范规定了2种类型的DNS服务器,一个叫主DNS服务器,一个叫辅助DNS服务器。在一个区中主DNS服务器从自己本机的数据文件中读取该区的DNS数据信息,而辅助DNS服务器则从区的主DNS服务器中读取该区的DNS数据信息。当一个辅助DNS服务器启动时,它需要与主DNS服务器通信,并加载数据信息,这就叫做区传送(zone transfer)。 

为什么既使用TCP又使用UDP? 
首先了解一下TCP与UDP传送字节的长度限制: 
   UDP报文的最大长度为512字节,而TCP则允许报文长度超过512字节。当DNS查询超过512字节时,协议的TC标志出现删除标志,这时则使用TCP发送。通常传统的UDP报文一般不会大于512字节。 

区域传送时使用TCP,主要有一下两点考虑: 
1.辅域名服务器会定时(一般时3小时)向主域名服务器进行查询以便了解数据是否有变动。如有变动,则会执行一次区域传送,进行数据同步。区域传送将使用TCP而不是UDP,因为数据同步传送的数据量比一个请求和应答的数据量要多得多。 
2.TCP是一种可靠的连接,保证了数据的准确性。 

域名解析时使用UDP协议: 
客户端向DNS服务器查询域名,一般返回的内容都不超过512字节,用UDP传输即可。不用经过TCP三次握手,这样DNS服务器负载更低,响应更快。虽然从理论上说,客户端也可以指定向DNS服务器查询的时候使用TCP,但事实上,很多DNS服务器进行配置的时候,仅支持UDP查询包。

当网站的访问量大了就会考虑负载均衡,这也是每一个架构师的基本功。传统的负载均衡思路是单点的。网站的响应速度很大程度上局限于负载均衡节点的能力,而且一旦负载均衡节点本身挂掉的话,整个网站就完全瘫痪了。

dns系统是一个典型的树状架构,上图所示的dns服务器其实应该叫dns缓存查询服务器,它是为了减轻互联网上dns查询的负载所设计的。如果你的请求没有命中缓存,那么这个缓存服务器就会自己进行一次标准查询,然后再把结果缓存起来,简单来说就是从根服务器开始一级一级的问。我们以前经常谈到根服务器的重要性其实就体现在这里了,它保留了对所有域名的起始解释权。

  1. dns系统本身是一个分布式的网络,它是相对可靠的,起码比你网站本身可靠的多
  2. dns的最终解释是可以受我们自己控制的

只需要在最终解释的查询结果上做文章就可以了。简单来说,就是将你的所有服务器地址,按照自己需求制定的频次,返回给用户。

二 HTTP

1 ★★★ GET 与 POST 比较:作用、参数、安全性、幂等性、可缓存。

HTTP全称为Hyper Text Transfer Protocol,中文翻译为超文本传输协议,目的是保证浏览器与服务器之间的通信。HTTP的工作方式是客户端与服务器之间的请求-应答协议。

HTTP协议中定义了浏览器和服务器进行交互的不同方法,基本方法有4种,分别是GET,POST,PUT,DELETE。这四种方法可以理解为,对服务器资源的查,改,增,删。

GET:从服务器上获取数据,也就是所谓的查,仅仅是获取服务器资源,不进行修改。

POST:向服务器提交数据,这就涉及到了数据的更新,也就是更改服务器的数据。

PUT:PUT的英文含义是放置,也就是向服务器新添加数据,就是所谓的增。

DELETE:从字面意思也能看出,这种方式就是删除服务器数据的过程。
 

1、GET交互方式是从服务器上获取数据,而并非修改数据,所以GET交互方式是安全的。就像数据库查询一样,从数据库查询数据,并不会影响数据库的数据信息,对数据库来说,也就是安全的。






2、GET交互方式是幂等的,幂等是一个数学概念,幂等函数就是可以使用相同参数重复执行,并且能获得相同结果的函数。在GET交互这里就是,对同一个URL的多个请求,得到的结果是相同的。就像数据库查询,不同的数据库连接对同一个数据库表用相同条件查询时,得到的结果也是一样的。



 

POST交互

1、POST交互是可以修改服务器数据的一种方式,涉及到信息的修改,就会有安全问题。就像数据库的更新,Update一个数据库表时,如果条件没有写对,就可能把不需要修改的数据给修改了,得到的数据就是错误的了。

2、一般的POST交互是必须要用到表单的,但是表单提交的默认方法是GET,如果改为POST方式,就需要修改表单提交时的Method。
 

两者的区别

GET方式:

1、GET方式是以实体的方式得到由请求URL所指定资源的信息,如果请求URL只是一个数据产生过程,那么最终要在响应实体中返回的是处理过程的结果所指向的资源,而不是处理过程的描述。也就是说,GET的到的信息是资源,而不是资源的处理过程。

2、请的求的数据会附加在URL之后,以?分隔URL和传输数据,多个参数用&连接。URL编码格式采用的是ASCII编码,而不是Unicode,即所有的非ASCII字符都要编码之后再传输。

3、因为URL的长度限制,GET方式传输的数据大小有所限制,传送的数据量不超过2KB。

4、GET方式服务器端用Request.QueryString获取变量的值。

5、GET方式传输的参数安全性低,因为传输的数据会显示在请求的URL中。

POST方式:

1、用来向目的服务器发出请求,要求它接收被附在请求后的实体,并把它当做请求队列中请求URL所指定资源的附加新子项。

2、POST方式将表单内各个字段和内容放置在HTML HEADER中一起传送到Action属性所指定的URL地址,用户是看不到这个过程的。

3、POST方式传送的数据量比较大,一般被默认为没有限制,但是根据IIS的配置,传输量也是不同的。

4、POST方式在服务器端用Request.Form获取提交的数据。

5、POST方式传输的数据安全性较高,因为数据传输不是明显显示的。
 

总结

POST和GET方式的安全性是相对的,另外也要看是从哪个角度来看的。从数据传输过程方面来看,POST方式是更加安全的,但是从对服务器数据的操作来看,POST方式的安全性又是比较低的。即使是传输过程用POST来执行,安全性也是相对的,如果了解HTTP协议漏洞,通过拦截发送的数据包,同样可以修改交互数据,所以这里的安全不是绝对的。

2 ★★☆ HTTP 状态码

当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求。

HTTP状态码的英文为HTTP Status Code。

下面是常见的HTTP状态码:

  • 200 - 请求成功
  • 301 - 资源(网页等)被永久转移到其它URL
  • 404 - 请求的资源(网页等)不存在
  • 500 - 内部服务器错误

HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:

<caption> HTTP状态码分类 </caption>
分类 分类描述
1** 信息,服务器收到请求,需要请求者继续执行操作
2** 成功,操作被成功接收并处理
3** 重定向,需要进一步的操作以完成请求
4** 客户端错误,请求包含语法错误或无法完成请求
5** 服务器错误,服务器在处理请求的过程中发生了错误

3 ★★★ Cookie 作用、安全性问题和 Session 的比较。

是什么

Cookie是服务的发送到用户浏览器并保存在本地的一小块数据,它会在浏览器之后的请求中发送给服务器,用户告知两个请求来自同一浏览器。

作用

HTTP请求是无状态的,使用Cookie可以用来保存状态信息。
例如可以用来保存Session ID

Cookie曾用作客户端数据的存储,但现在新的浏览器已经支持各种方式的本地存储,如storage API或Indexed DB,Cookie已经被淘汰了。

cookie分为二种

1,以文件方式存在硬盘空间上的长期性的cookie

2,停留在浏览器所占内存中的临时性的cookie

session是一种服务器端的信息管理机制,它把这些文件信息以文件的形势存放在服务器的硬盘空间上,这种情况是默认的,可以用memcache把这种数据放到内存里面。请参考web集群时利用memcache来同步session

当客户端向服务器发出请求时,要求服务器端产生一个session时,服务器端会先检查一下,客户端的cookie里面有没有session_id,是否已经过期。如果有这样的session_id的话,服务器端会根据cookie里的session_id把服务器的session检索出来。如果没有这样的session_id的话,服务器端会重新建立一个。PHPSESSID是一串加了密的字符串,它的生成按照一定的规则来执行。同一客户端启动二次session_start的话,session_id是不一样的。

session和cookie谁更安全

就个人而言,我觉得session更安全一点,我以下几点看法。

1,如果session和cookie一样安全的话,二者就没有并要同时存在了,只要cookie就好了,让客户端来分提服务器的负担,并且对于用户来说又是透明的。何乐而不为呢。

2,session的sessionID是放在cookie里,要想功破session的话,第一要功破cookie。功破cookie后,你要得到 sessionID,sessionID是要有人登录,或者启动session_start才会有,你不知道什么时候会有人登录。第二,sessionID是加密的,第二次session_start的时候,前一次的sessionID就没有用了,session过期时sessionid也会失效,想在短时间内功破加了密的 sessionID很难。session是针对某一次通信而言,会话结束session也就随着消失了,而真正的cookie存在于客户端硬盘上的一个文本文件,谁安全很显然了。

3,如果session这么容易被功破,这么不安全的话,我想现有的绝大部分网站都不安全了。

与Cookie不同Session是保存在服务器上的。通过名为JSESSIONID的Cookie保存session id。

1.存取方式不同

Cookie只能报关ASCII字符串
Session能够存取任何类型的数据,如Java对象等

2.隐私策略不同

Cookie存储在浏览器中,对浏览器是可见的,客户端的一些程序可以查看、复制甚至修改Cookie中的内容。而Session存储在服务器上,对客户端是透明的,不存在敏感信息泄露风险

假如使用Cookie存储账号密码等信息,最好进行加密后再存储,提交到服务器后再进行解密。

3有效期不同

Cookie可设置过期时间。默认是浏览器关闭。

Session依赖于名为JSESSIONID的cookie,而该Cookie的过期时间为-1,表示只要关了浏览器就过期,而该服务器上的对应session也就失效了。假如设置session的超时时间过程,服务器累计的Session就会越多,越容易招致内存溢出

4.服务器压力不同

Session保存在服务器上,每个用户都会产生一个session,假如并发用户十分多,会产生十分多的session,消耗大量的内存。

Cookie保存在客户端,不占用服务器资源。

5.浏览器支持不同

Cookie是需要浏览器支持的。假如浏览器禁用了cookie,则不能使用cookie

6.跨域支持上的不同

Cookie支持跨域访问。Session不支持

4 ★★☆ 缓存 的Cache-Control 字段,特别是 Expires 和 max-age 的区别。ETag 验证原理

HTTP缓存机制分为两种,客户端缓存服务端缓存。

客户端侧缓存一般指的是浏览器缓存,目的就是加速各种静态资源的访问,想想现在的大型网站,随便一个页面都是一两百个请求,每天 pv 都是亿级别,如果没有缓存,用户体验会急剧下降、同时服务器压力和网络带宽都面临严重的考验。

客户端缓存主要是HTTP协议定义的缓存机制(如 Expires, Cache-Control字段), 也有非HTTP协议定义的缓存,使用HTTP-MATE标签

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">

上述代码的作用是告诉浏览器当前页面不被缓存,每次访问都需要去服务器拉取。使用上很简单,但只有部分浏览器可以支持,而且所有缓存代理服务器都不支持,因为代理不解析HTML内容本身。

Expires是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。 不过Expires 是HTTP 1.0的东西,现在默认浏览器均默认使用HTTP 1.1,所以它的作用基本忽略。

Cache-Control与Expires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。只不过Cache-Control的选择更多,设置更细致,如果同时设置的话,其优先级高于Expires。

HTTP-Header中的Cache-Control字段:
可以是public、private、no-cache、no- store、no-transform、must-revalidate、proxy-revalidate、max-age

各个消息中的指令含义如下:

public指示响应可被任何缓存区缓存。

private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。

no-cache指示请求或响应消息不能缓存

no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。

max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。

min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。

max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。
 

http首部Expires和Cache-Control字段是服务端用来约定和客户端的有效时间,格式如下:

1
2
Expire:Thu, 31 Dec 2037 23:55:55 GMT
Cache-Control: max-age = 315360000

 

  1. 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在response的header会加上Expires/cach-control的header;

  2. 浏览器再请求这个资源时,先从缓存中寻找,找到这个资源后,比较expires或cache-control的max-age字段值做比较, 如果在有效期内,则缓存命中,读取缓存内容,否则重新向服务器发送请求;

  3. Header在重新加载的时候会被更新

  4. 联系和区别

  5. Expires规定了缓存失效时间(Date为当前时间),而Cache-Control的max-age规定了缓存有效时间(2552s), 前者是绝对时间,后者是相对时间
  6. Expires是HTTP1.0的东西,而Cache-Control是HTTP1.1的
  7. 若响应头Expires和Cache-Control同时存在,Cache-Control优先级高于Expire
  8. Exipires返回的是一个绝对时间,在服务器时间与客户端时间相差较大的时候,缓存命中不准确,如:随意修改客户端时钟。
  9. 如果单只设置有效时间,如文件过了有效期后,内容并没有发生改变,还是可以用缓存数据,这个时候又怎么判断服务端文件有没有更新呢?主要有两种方式:

  10. Last-Modified,If-Modified-since: 在约定有效期的基础上,增加文件是否修改的字段进行再次验证
  11. ETag, If-None-Match: 在约定有效期的基础上,增加文件版本号的验证
  12. ETag, If-None-Match原理

    ETag解决了Last-Modifiend的缺陷,ETag不仅仅跟最后修改时间决定, 它是根据当前请求的资源生成的一个唯一标识符(默认是由文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的)

    1
    
    ETag: "17fd8-5291a5f96fd20"
    

     

  13. 浏览器第一次向服务器请求一个资源,服务器在返回这个资源的同时,在respone的header加上ETag字段;

  14. 浏览器再次跟服务器请求这个资源时,在request的header上加上If-None-Match,这个值就是上一次请求时返回的ETag的值;

  15. 服务器再次收到资源请求时,再根据资源生成一个新的ETag,与浏览器传过来If-None-Match比较,如果这两个值相同就说明资源没有变化,则返回304 Not Modified, 浏览器从缓存中加载资源,否则返回200 资源内容。与Last-Modified不一样的是,当服务器返回304 Not Modified的响应时,由于ETag重新生成过,response header中还会把这个ETag返回,即使这个ETag跟之前的没有变化

5 ★★★ 长连接与短连接原理以及使用场景,流水线

定义:

短连接:例如普通的web请求,在三次握手之后建立连接,发送数据包并得到服务器返回的结果之后,通过客户端和服务端的四次握手进行关闭断开。

长连接:区别于短连接,由于三次握手链接及四次握手断开,在请求频繁的情况下,链接请求和断开请求的开销较大,影响效率。采用长连接方式,执行三次握手链接后,不断开链接,保持客户端和服务端通信,直到服务器超时自动断开链接,或者客户端主动断开链接。

适用场景:

短连接:适用于网页浏览等数据刷新频度较低的场景。

长连接:适用于客户端和服务端通信频繁的场景,例如聊天室,实时游戏等。

 非持久连接:每个连接处理一个请求-响应事务。

    2. 持久连接:每个连接可以处理多个请求-响应事务。

        持久连接情况下,服务器发出响应后让TCP连接继续打开着。同一对客户/服务器之间的后续请求和响应可以通过这个连接发送。

      3. HTTP/1.0 使用非持久连接。     HTTP/1.1 默认使用持久连接。

持久连接、不带流水线(without pipelining)、带流水线(with pipelining)

    3.1 不带流水线(without pipelining)、带流水线(with pipelining)

        1.  不带流水线(without pipelining):客户只在收到前一个请求的响应后,才发出新的请求。

            与非持久连接2个RTT的延迟相比,不带流水线的持久连接已有所改善。

        2.  带流水线(with pipelining):HTTP客户每碰到一个引用就立即发送一个请求,即HTTP客户可以一个接  一个挨着发送各个引用对象的请求。服务器收到这些请求后,也可以一个接一个的发送各个对象的响应。

           带流水线,所有引用到的对象一共只经历1个RTT的延时,而不带流水线,每个引用到的对象各有1个RTT的延迟。

           带流水线的持久连接中服务器空等请求的时间较少。

6 ★★★ HTTP 存在的安全性问题,以及 HTTPs 的加密、认证和完整性保护作用。

 

HTTP是客户端浏览器或其他程序与Web服务器之间的应用层通信协议。在Internet上的Web服务器上存放的都是超文本信息,客户机需要通过HTTP协议传输所要访问的超文本信息。

HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。

鉴于HTTP的缺点,HTTPS在HTTP的基础上增加了:

  • 通信加密
  • 证书认证
  • 完整性保护

HTTP问题:

通信内容为明文,即未加密,内容可能会被窃听。

通信双方的身份没有进行验证,可能出现伪装身份的情况。

接受的报文完整性无法确定,可能中途被改动。

http是HTTP协议运行在TCP之上。所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。

https是HTTP运行在SSL/TLS之上,SSL/TLS运行在TCP之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。此外客户端可以验证服务器端的身份,如果配置了客户端验证,服务器方也可以验证客户端的身份。

SSL会使通信的效率降低

  • 通信速率降低
    HTTPS 除了TCP连接,发送请求,响应之外,还需要进行SSL通信。整体通信信息量增加。
  • 加密过程消耗资源
    每个报文都需要进行加密和解密的运算处理。比起HTTP会消耗更多的服务器资源。
  • 证书开销
    如果想要通过HTTPS进行通信,就必须向认证机构购买证书。

7 ★★☆ HTTP/1.x 的缺陷,以及 HTTP/2 的特点。

  • 新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。

  • 多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。

  • header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。

  • 服务端推送(server push),同SPDY一样,HTTP2.0也具有server push功能。

8 ★★★ HTTP/1.1 的特性。

HTTP1.1版本优点:

  • 增加持久性连接:增加持久性连接的某些特性。
  • 增加管道机制:首先简单介绍一下HTTP1.0版本时请求的特点增加了管道机制,请求可以同时发出,但是响应必须按照请求发出的顺序依次返回,性能在一定程度上得到了改善
  • 分块传输:可以没必要等待数据完全处理完毕再返回,服务器产生部分数据,那么就发送部分数据,很明此种方式更加优秀一些,可以节省很多等待时间。
  • 增加host字段:在头部增加host字段,在部署网站的时候没有必要买昂贵的独立服务器,只要买虚拟主机即可,成本大大降低。

HTTP1.1版本缺陷:

  • 此版本的网络延迟问题主要由于队头堵塞导致,虽然通过持久性连接得到改善,但是每一个请求的响应依然需要按照顺序排队,如果前面的响应处理较为耗费时间,那么同样非常耗费性能。
  • 此版本虽然引进了管道机制,但是当前存在诸多问题,且默认处于关闭状态。

9 ★★☆ HTTP 与 FTP 的比较。

  • HTTP协议是用来浏览网站的,而FTP是用来访问和传输文件的,FTP文件传输有点批量上传和维护网站的意思,而HTTP文件传输更多的是为终端用户提供文件传输,比如电影、图片、音乐之类。
  • HTTP 和 FTP 客户端:通常的HTTP客户端就是浏览器,而FTP服务可以通过命令行或者用户自有的图形界面客户端。
  • HTTP 头:HTTP 头包含了 metadata ,比如说最后更改的日期、编码方式、服务器名称版本还有其他的一些信息,而这些在FTP中是不存在的。
  • FTP要比HTTP出现10年左右。
  • 数据格式:FTP能传输ACSII数据或者二进制格式的数据,而HTTP只用二进制格式。
  • HTTP中的流水线:HTTP支持流水线,这就意味着客户端可以在上一个请求处理完之前,发出下一个请求,其结果就是多次请求数据之前省掉了部分服务器客户端往返时延。而FTP并没有这项支持。
  • HTTP中的动态端口:FTP一个最大的问题就是它使用两个连接,第一个连接用来发送控制指令,当接受或者发送数据的时候,又打开第二个TCP连接。而HTTP在双向传输中使用动态端口。
  • HTTP中的持久连接:对一个HTTP会话来讲,客户端可以维护一个单个的连接并使用它进行任意数量的数据传输。FTP每次有数据的需要时都创建一个新的连接。重复的创建新的连接带来的体验并不好,因为每次创建连接都必须让双方握手验证,这消耗了很多时间。
  • HTTP中的压缩算法:HTTP提供了一个在一些压缩算法中客户端和服务器共同协商选择的办法。其中gzip可以说是最有影响力的一种,而FTP中并不存在这种复杂的算法。
  • HTTP支持代理:HTTP一个很大的特点就是支持代理,这种功能是构建在协议里的,而FTP并不支持。
  • FTP也能脱颖而出的一点是这个协议是直接面向文件级别的。这以为着FTP有例如可以通过命令列出远程服务器上的目录列表,而HTTP没有这个概念。
  • 速度:可能最通常的问题了:哪一个传输更快?

什么使FTP服务更快?

  • 没有在发出的数据中加入meta-data,仅传输原二进制文件。
  • 没有过度的分块编码

什么使HTTP服务更快?

  • 重用已存在的持久连接,从而有更好的TCP表现。
  • 流水线的支持使得从同一个服务器上请求多个文件更快。
  • 自动的压缩机制使得传输的数据更少。
  • 没有命令/应答机制最大限度的减少了往返时延。

总结:当然最终的结果会因具体的情况而异,但我(原作者)想说的是,单次传输一个静态的文件,很难衡量两者的区别对单个的小文件来说,FTP传输更快,当传输多个文件时,HTTP更快。

三 Socket

1 ★★☆ 五种 IO 模型的特点以及比较

为了保证操作系统的安全,将内存划分为内核空间和用户空间。内核空间的进程,可以访问硬件执行IO等操作,用户空间的进程只能通过系统调用来访问IO等系统资源。

IO模型的区分依据

对于一次IO访问(以read举例),数据会先被拷贝到操作系统内核的缓冲区中,然后再拷贝到应用程序的地址空间。
所以,当一个read操作发生时,它会经历两个阶段

  • 等待数据准备(Waiting for the data to be ready)
  • 将数据从内核拷贝到进程中(Copying the data from the kernel to the process)

正是因为这两个阶段,linux系统产生了下面五种网络模型:

  • 阻塞IO 特点:在IO执行的两个阶段进程都会阻塞
  • 非阻塞IO 特点:需要进程不断地主动询问kernel数据是否准备好了
  • IO多路复用 :单个进程处理多个网络连接IO,使用select\poll\epoll三种系统调用,不断轮询所有的连接,如果有数据到达内核则通知进程,进行数据拷贝到用户内存。 多路IO复用的优势并不是对于单个连接能处理的更快,而在于能处理更多的连接
  • 信号驱动IO
  • 异步 IO :发起read操作后进程立马返回,整个Io过程不会产生任何block。kernel会等等数据准备完成,然后将数据拷贝到用户内存。当这一切都完成后,kernel会给用户进程发送一个signal,告诉它read操作完成了

阻塞IO和非阻塞IO的区别

  • 调用blocking io会一直block进程直到操作完成
  • no-blocking io在kernel准备数据的阶段是会立刻返回

同步和异步的区别

  • 只有异步IO是异步IO
  • 其他3种:阻塞IO、非阻塞IO、多路复用IO都是同步的

这是因为其他三种IO在执行真实IO操作的过程中都有进程阻塞的阶段,而异步IO在整个过程中进程都没有被阻塞。非阻塞IO在内核数据就绪,拷贝到用户空间的阶段也是阻塞的,因此也是同步IO。

 select、poll、epoll 的原理、比较、以及使用场景;epoll 的水平触发与边缘触发。

我们都知道unix(Linux)世界里,一切皆文件,而文件是什么呢?文件就是一串二进制流而已,不管socket,还是FIFO、管道、终端,对我们来说,一切都是文件,一切都是流。在信息交换的过程中,我们都是对这些流进行数据的收发操作,简称为I/O操作(input and output),往流中读出数据,系统调用read,写入数据,系统调用write。不过话说回来了 ,计算机里有这么多的流,我怎么知道要操作哪个流呢?对,就是文件描述符,即通常所说的fd,一个fd就是一个整数,所以,对这个整数的操作,就是对这个文件(流)的操作。我们创建一个socket,通过系统调用会返回一个文件描述符,那么剩下对socket的操作就会转化为对这个描述符的操作。不能不说这又是一种分层和抽象的思想。

IO操作具体又分两部分: 

  • 第一部分:等待数据的就绪,也就是文件描述符上有事件就绪,我们才可以对其进行IO操作 
  • 第二部分:数据搬迁,说白了就是将一个文件中的数据搬到另一个文件中

什么是IO多路复用/转接
I/O多路复用实际上就是用select, poll, epoll监听多个io对象,当io对象有变化(有数据)的时候就通知用户进程。好处就是单个进程可以处理多个socket。IO多路复用可以大大的降低等待事件就绪的时间,从而有效的提高IO效率。

下面介绍三种IO复用的接口实现,原理解释以及三种方式的对比:
select: 用户将自己所关心的文件描述符添加进描述符集中,并且明确关心的是读,写,还是异常事件。select通过轮询的方式不断扫描所有被关心的文件描述符,具体时间由参数timeout决定。执行成功则返回文件描述符状态已改变的个数。具体哪一个或哪几个文件描述符就绪,则需要文件描述符集传出,它既是输入型参数,又是输出型参数。fd_set是用位图存储文件描述符的,因为文件描述符是唯一且递增的整数。可关心的文件描述符数量是有上限的,取决于fd_set的大小。每次调用select前,都要把文件描述符重新添加进去fd_set中,因为fd_set也是输出型参数,在函数返回后,fd_set中只有就绪的文件描述符通常我们要关心的文件描述符不止一个,所以首先用数组保存文件描述符,每次调用select前再通过遍历数组逐个添加进去

缺点:

  • 每次调用select都需要手动设置fd_set集合
  • 每次调用select需要遍历fd_set集合,而且要将fd_set集合从用户态拷贝到内核态,如果fd很多时,开销会很大
  • select支持的文件描述符数量太少

poll:

首先创建一个pollfd结构体变量的数组fd_list,然后将我们关心的fd放置在数组中的结构体变量中,并添加我们所关心的事件,调用poll函数,函数返回后我们再通过遍历的方式去查看数组中那些文件描述符上的事件就绪了。

特点(相对与select来说)

每次调用poll之前不需要手动设置文件描述符集
poll将用户关心的事件和发生的事件进行了分离
支持的文件描述符数量理论上是无上限的,其实也有,因为一个进程能打开的文件数量是有上限的 ulimit -n 查看进程可打开的最大文件数
缺点

poll返回后,也需要轮询pollfd来获取就绪的描述符
同时连接的大量客户端可能只有很少的处于就绪状态,因此随着监视的描述符数量的增长,其效率也会线性下降

epoll:

创建一个epoll对象,向epoll对象中添加文件描述符以及我们所关心的在该文件描述符上发生的事件。通过epoll_ctl向我们需要关心的文件描述符中注册事件(读,写,异常等),操作系统将该事件和对应的文件描述符作为一个节点。入到底层建立的红黑树中。添加到文件描述符上的事件都会与网卡建立回调机制,也就是事件发生时会自主调用一个回调方法,将事件所在的文件描述符插入到就绪队列中。用程序调用epoll_wait就可以直接从就绪队列中将所有就绪的文件描述符拿到,可以说时间复杂度是O(1)

水平触发工作方式(LT)

处理socket时,即使一次没将数据读完,下次调用epoll_wait时该文件描述符也会就绪,可以继续读取数据

边沿触发工作方式(ET)

处理socket时没有一次将数据读完,那么下次再调用epoll_wait该文件描述符将不再显示就绪,除非有新数据写入

在该工作方式下,当一个文件描述符就绪时,我们要一次性的将数据读完

隐患问题

当我们调用read读取缓冲区数据时,如果已经读取完了,对端没有关闭写端,read就会阻塞,影响后序逻辑

解决方式就是将文件描述符设置成非阻塞的,当没有数据的时候,read也不会被阻塞,可以处理后续逻辑(读取其他的fd或者继续wait)

ET的性能要好于LT,因为epoll_wait返回的次数比较少,Nginx中默认采用ET模式使用epoll

epoll特点

采用了回调机制,与轮询区别看待
底层采用红黑树结构管理已经注册的文件描述符
采用就绪队列保存已经就绪的文件描述符

优点:文件描述符数目无上限:通过epoll_ctl注册一个文件描述符后,底层采用红黑树结构来管理所有需要监控的文件描述符
基于事件的就绪通知方式:每当有文件描述符就绪时,该响应事件会调用回调方法将该文件描述符插入到就绪队列中,不需要内核每次去轮询式的查看每个被关心的文件描述符。维护就绪队列:当文件描述符就绪的时候,就会被放到内核中的一个就绪队列中,调用epoll_wait可以直接从就绪队列中获取就绪的文件描述符,时间复杂度是O(1)
惊群问题 
当有多个子进程在阻塞等待同一个文件描述符上的某事件时,如果该事件发生,那么所有的子进程都会被唤醒 
进程被唤醒,需要进行内核重新调度,这样每个进程同时去响应这一个事件,而最终只有一个进程能处理事件成功,其他的进程在处理该事件失败后重新休眠或其他。会造成性能浪费 
早期版本中,Linux中采用全部唤醒的机制,极大浪费性能,目前版本中,采用的是只唤醒等待队列上的第一个进程或线程,但是selec、poll和epoll中还存在部分的惊群问题

惊群问题解决方法 
Nginx中使用mutex互斥锁解决这个问题,具体措施有使用全局互斥锁,每个子进程在epoll_wait()之前先去申请锁,申请到则继续处理,获取不到则等待,并设置了一个负载均衡的算法(当某一个子进程的任务量达到总设置量的7/8时,则不会再尝试去申请锁)来均衡各个进程的任务量。
 


以上是计算机网络相关的一些问题,下一篇将为大家整理数据库以及其他问题。