网络协议分层
国际标准化组织 ISO 提出了 OSI 开放互连的七层计算机网络模型,从上到下分别是应用层、表示层、会话层、运输层、网络层、链路层和物理层。OSI 模型的概念清楚,理论也比较完善,但是既复杂又不实用。还有一种是 TCP/IP 体系结构,它分为四层,从上到下分别是应用层、运输层、网际层和网络接口层,不过从实质上将只有三层,因为最下面的网络接口层并没有什么具体内容。因特网的协议栈使用一种五层的模型结构,从上到下依次是应用层、运输层、网络层、链路层和物理层,其中下层是为上层提供服务的,每层执行某些动作或使用下层的服务来提高服务。
应用层
应用层是网络体系结构中的最高层,应用层的任务就是通过应用进程之间的交互来完成特定网络应用,这一层的数据单元叫做报文。
应用层的协议定义了应用进程之间通信和交互的规则,主要包括了域名系统 DNS、支持万维网的 HTTP 协议、支持电子邮件的 SMTP 协议、文件传输协议 FTP 等。
域名解析系统 DNS
DNS 被设计为一个联机分布式数据库系统,并采用客户服务器方式。DNS 使大多数名字都在本地进行解析,仅少量解析需要在互联网上通信,因此 DNS 的效率很高。由于 DNS 是分布式系统,即使单个计算机出现了故障也不会妨碍到整个 DNS 系统的正常运行。
主机向本地域名服务器的查询一般都采用递归查询,递归查询指如果主机所询问的本地域名服务器不知道被查询域名的 IP 地址,那么本地域名服务器就以 DNS 客户的身份向其他根域名服务器继续发出查询请求报文。递归查询的结果是要查询的 IP 地址,或者是报错,表示无法查询到所需的 IP 地址。
本地域名服务器向根域名服务器查询通常采用迭代查询,迭代查询指当根域名服务器收到本地域名服务器发出的迭代查询请求报文时,要么给出所要查询的 IP 地址,要么告诉它该向哪一个域名服务器进行查询。本地域名服务器也可以采用递归查询,这取决于最初的查询请求报文设置的查询方式。
文件传送协议 FTP
FTP 使用 TCP 可靠的运输服务,FTP 使用客户服务器方式,一个 FTP 服务器进程可以同时为多个客户进程提供服务,在进行文件传输时,FTP 的客户和服务器之间要建立两个并行的 TCP 连接:控制连接和数据连接,实际用于传输文件的是数据连接。
电子邮件系统协议 SMTP/POP3/IMAP
一个电子邮件系统有三个主要组成构件,即用户代理、邮件服务器、以及邮件协议。
从用户代理把邮件传送到邮件服务器,以及在邮件服务器之间的传送都要使用 SMTP,但用户代理从邮件服务器读取邮件时则要使用 POP3 或 IMAP 协议。
基于万维网的电子邮件使用户可以利用浏览器收发电子邮件,用户浏览器和邮件服务器之间使用 HTTP 协议,而邮件服务器之间的传送仍然使用 SMTP 协议。
运输层
运输层的任务就是负责向两台主机中进程之间的通信提供通用的数据传输服务,应用进程利用该服务来传送应用层报文。由于一台主机同时可以运行多个进程,因此运输层具有复用和分用的功能,复用就是多个应用层进程可以同时使用下面运输层的服务,分用就是把运输层收到的信息分别交付给上面应用层中的对应进程。
运输层主要使用两种协议:① 用户数据报协议 UDP,这是一种提供无连接的、尽最大努力交付的数据传输服务,不保证数据传输的可靠性,数据传输单位是用户数据报。② 传输控制协议 TCP,这是一种面向连接的、可靠的数据传输服务,数据传输单元是报文。
网络层
网络层负责为分组交换网上的不同主机提供通信服务,在发生数据时,网络层把数据层产生的报文或用户数据报封装成分组进行传送,由于网络层使用 IP 协议,因此分组也叫 IP 数据报。网络层的另一个任务就是选择合适的路由,使源主机运输层所传下来的分组能够通过网络中的路由器找到目的主机。
网络层的协议包括了网际协议 IP、地址解析协议 ARP、网际控制报文协议 ICMP 以及路由选择协议 RIP/OSPF/BGP-4 等。
网际协议 IP
网际协议 IP 是 TCP/IP 体系中两个最主要的协议之一,一般指的是 IPv4。与 IP 协议配套使用的协议还有 ARP、ICMP 和 IGMP,IP 使用 ARP,ICMP 和 IGMP 要使用 IP。由于网际协议 IP 是用来使互连起来的许多计算机网络能够进行通信的,因此 TCP/IP 体系中的网络层也称网际层或 IP 层。要解决 IP 地址耗尽的问题,根本方法是采用具有更大地址空间的新版本 IP 协议即 IPv6,向 IPv6 过渡可以使用双协议栈或使用隧道技术。
地址解析协议 ARP
由于 IP 协议使用了 ARP 协议,因此把 ARP 协议归到网络层,但 ARP 的作用是通过一个 ARP 高速缓存存储本地局域网的各主机和路由器的 IP 地址到硬件地址的映射表,以从网络层的 IP 地址解析出在数据链路层使用的硬件地址,因此也可以把 ARP 划归在数据链路层。与 ARP 对应的协议是 RARP,逆地址解析协议,作用是使只知道自己硬件地址的主机能够找出 IP 地址,但被 DHCP 协议取代。
路由选择协议 RIP/OSPF/BGP-4
路由选择协议有两大类:内部网关协议,如 RIP 和 OSPF;外部网关协议,如 BGP-4。
RIP 是分布式的基于距离向量的路由选择协议,只适用于小型互联网。RIP 按照固定的时间间隔与相邻路由器交换信息,交换的信息是当前路由表。OSPF 是分布式的链路状态协议,适用于大型互联网,只在链路状态发生变化时才向本自治系统中的所有路由器用洪泛法发送与本路由器相邻的所有路由器的链路状态信息。
BGP-4 是不同自治系统的路由器之间交换路由信息的协议,是一种路径向量路由选择协议。其目标是寻找一条能够到达目的网络且比较好的路由而不是最佳路由。
网际控制报文协议 ICMP
ICMP 报文作为 IP 数据报的数据,加上首部后组成 IP 数据报发送出去,使用 ICMP 并非为了实现可靠传输,ICMP 允许主机或路由器报告差错情况和提供有关异常情况的报告。ICMP 报文的种类有两种,即 ICMP 差错报告报文和 ICMP 询问报文。
ICMP 的一个重要应用就是分组间探测 PING,用来测试两台主机之间的连通性,PING 使用了 ICMP 回送请求与回送回答报文。
网际组管理协议 IGMP
IP 多播使用 IGMP 协议,IGMP 并非在互联网范围内对所有多播组成员进行管理,它不知道 IP 多播组包含的成员个数也不知道这些成员都分布在哪些网络上。
IGMP 协议是让连接在本地局域网上的多播路由器知道本局域网上是否有主机上的某个进程参加或推出了某个多播组。
链路层
数据链路层的任务是将网络层交下来的 IP 数据报组装成帧,在两个相邻结点之间的链路上传输帧,每一帧包括数据和必要的控制信息(同步信息、地址信息、差错控制等)。在接收数据时,控制信息使接收端能够知道一个帧从哪个比特开始到哪个比特结束,这样链路层就可以从帧中提取出数据部分上交给网络层。控制信息还使接收端能够检测到所收到的帧有无差错,如果有差错就简单地丢弃这个帧以免继续传送而浪费网络资源。
数据链路层的协议包括了点对点协议 PPP 和 CSMA/CD 协议等。
点对点协议 PPP
在通信线路质量较差的年代,使用高级数据链路控制 HDLC 作为实现可靠传输的数据链路层协议,但现在 HDLC 已经很少使用了,对于点对点的链路,简单得多的点对点协议 PPP 是目前使用得最广泛的数据链路层协议。PPP 协议的特点是简单、只检测差错而不纠正差错、不使用序号也不进行流量控制、可同时支持多种网络层协议。
CSMA/CD 协议
以太网采用的是具有冲突检测的载波监听多点接入 CSMA/CD 协议,协议的要点是:发送前先监听、边发送边监听,一旦发现总线上出现了碰撞就立即停止发送。然后按照退避算法等待一段随机时间后再次发送,因此每一个站在自己发送数据之后的一小段时间内存在遭遇碰撞的可能性。以太网上各站点都平等地争用以太网信道。
物理层
物理层的任务是尽可能地屏蔽掉传输媒体和通信手段的差异,使物理层上面的数据链路层感觉不到这些差异,使其只需考虑本层的协议和服务。
物理层所传输的数据单位是比特,发送方发送 1 或 0,接收方也接收 1 或 0,因此物理层需要考虑用多大的电压代表 1 或 0,以及接收方如何识别出发送方所发送的比特。除此之外,物理层还要确定连接电缆的插头应当有多少根引以及各引脚如何连接等问题。
TCP
TCP 特点
TCP 是面向连接的运输层协议,一个应用进程在向另一个进程发送数据之前,两个进程必须先建立 TCP 连接,发送某些预备报文段,建立确保数据传输的参数。作为 TCP 连接建立的一部分,连接双方都将初始化与 TCP 连接相关的许多状态变量。这种连接不是电路交换网络中的端到端电路这种物理连接,而是一种逻辑连接,TCP 报文要先传送到 IP 层加上 IP 首部后,再传到数据链路层,加上链路层的首部和尾部后才离开主机发送到物理层。
TCP 连接提供全双工服务,允许通信双方的应用进程在任何时候都能发送数据。TCP 连接的两端都有各自的发送缓存和接收缓存,用来临时存放通信数据。在发送时,应用程序把数据传送给 TCP 缓存后就可以做自己的事,而 TCP 在合适的时候会把数据发送出去。在接收时,TCP 把收到的数据放入缓存,上层应用程序会在合适的时候读取缓存数据。
TCP 连接是点对点的,每一条 TCP 连接只能有两个端点,即只能是单个发送方和单个接收方之间的连接。
TCP 提供可靠的交付服务,通过 TCP 连接传送的数据无差错、不丢失、不重复,按序到达。
TCP 是面向字节流的,流是指流入到进程或从进程中流出的字节序列。面向字节流的含义是:虽然应用程序和 TCP 的交互是一次一个数据块,但是 TCP 把应用程序交下来的数据仅仅看成一连串无结构的字节流。TCP 不保证接收方应用程序收到的数据块和发送方应用程序发出的数据块具有对应大小的关系,但是接收方应用程序收到的字节流必须和发送方应用程序发出的字节流完全一样。接收方应用程序必须有能力识别收到的字节流,并把它还原成有意义的应用层数据。
TCP 报文结构
TCP 传送的数据单元是报文段,一个 TCP 报文段分为首部和数据两部分。首部的前 20 个字节是固定的,后面有 4n 字节是根据需要而增加的选项,因此 TCP 首部的最小长度是 20 字节.TCP 首部的重要字段如下:
**源端口和目的端口:**各占 2 字节,分别写入源端口号和目的端口号,TCP 的分用功能是通过端口实现的,分用就是指运输层从 IP 层收到发送给各应用进程的数据后,把数据交付给正确的套接字的工作。
**序号:**占 4 字节。TCP 是面向字节流的,在一个 TCP 连接中传送的字节流中的每一个字节都按顺序编号,首部中的序号字段值指的是本报文段所发送的数据的第一个字节的序号。序号使用 mod232 计算,每增加到 231-1 后下一个序号就又回到 0。
**确认号:**占 4 字节,是期望收到对方下一个报文段的第一个数据字节的序号。如果确认号为 N,代表到序号 N-1 为止的所有数据已经正确收到。序号有 32 位长,一般情况下可以保证当序号重复使用时,旧序号的数据早已通过网络到达终点了。
**数据偏移:**占 4 字节,实际是TCP 报文段的首部长度,指出了 TCP 报文段的数据起始处到 TCP 报文段的起始处的距离。由于首部中有长度不确定的选项字段,因此数据偏移字段是必要的。
**标志字段:**占 6 位。URG 是紧急标志,URG=1 时告诉系统此报文段中有紧急数据,应尽快传送,而不按照原来的排队顺序传送,和紧急指针配合使用,紧急指针指出了本报文段中紧急数据的字节数和位置。ACK 是确认标志,ACK=1 时表示成功接收了报文段。SYN 是同步标志,在建立连接时用来同步序号,当 SYN=1 而 ACK=0 时,表示一个连接请求报文段,响应时 SYN 和 ACK 都为 1,因此 SYN=1 表示一个连接请求或连接响应报文。FIN 是终止标志,用来释放一个连接,当 FIN=1 时表示报文段发送方的数据已发送完毕,并要求释放连接。PSH 是推送标志,PSH=1 时接收方就不等待整个缓存填满了再向上交付而是尽快交付数据。RST 是复位标志,当 RST=1 时表示 TCP 连接出现了严重错误,必须释放连接再重新建立连接。
**接收窗口:**占 2 字节,指的是发送本报文段一方的接收窗口,告诉对方从本报文首部的确认号算起允许对方发送的数据量。窗口值是用来限制发送方的发送窗口的,因为接收方的数据缓存空间是有限的。
**检验和:**占 2 字节,检验范围包括首部和数据两部分。在计算检验和时,要在 TCP 报文段的前面加上 12 字节的伪首部。
可靠传输协议 ARQ
自动重传请求 ARQ 包括了停止等待协议、回退 N 步协议和选择重传协议,后两种结合了窗口机制,属于连续 ARQ 协议。
停止等待协议
停止等待就是每发送完一个分组就停止发送,等待对方的确认,在收到确认之后再发送下一个分组。停止等待协议包括了三种情况:
1. 无差错情况
A 发送分组 M1,发送完后就暂停并等待 B 的确认。B 收到了 M1 之后就向 A 发送确认,当 A 收到确认之后就再发送下一个分组 M2。
2. 出现差错的情况
当 B 收到 M1 时检测出了差错就丢弃了 M1,其他什么也不做,也可能是 M1 在传输过程中丢失了,B 什么都不知道。在这两种情况下 B 都不会发送任何确认信息,解决方法是:A 只要超过一段时间没有收到确认就认为刚才发送的分组丢失了,因而重传前面发过的分组,这就叫超时重传。要实现超时重传,就要在每发送完一个分组时设置一个超时计时器,如果在超时计时器到期之间收到了对方的确认就进行撤销。
有三点需要注意:① A 在发送完一个分组后必须暂时保留已发送分组的副本在超时重传时使用,只有在收到确认后才清除副本。② 分组和确认分组都必须进行编号,这样才能明确是哪一个发送出去的分组进行了确认。③ 超时计时器设置的时间应当比数据在分组传输的平均往返时间稍长一些,如果设置过短会产生不必要的重传,如果设置过长会降低通信效率。
3. 确认丢失和确认迟到
B 发送的对 M1 的确认丢失了,A 在设定的超时重传时间内没有收到确认,并不知道是自己发送的问题还是 B 的问题,因此 A 就会超时重传。假设 B 又收到了重传分组 M1,此时 B 会采取两个行动:① 丢弃这个分组,不向上层交付。② 重新向 A 发送确认。
还有另一种情况就是 B 发送的确认并没有丢失但是迟到了,A 会受到重复的确认,此时 A 会收下并丢弃。通常 A 最终总是可以收到对所有发出的分组的确认,如果 A 不断重传分组但总是收不到确认,就说明通信线路质量太差,不能进行通信。
停止等待协议的优点是简单,但缺点是信道利用率太低。为了提高传输效率,发送方可以不使用停止等待协议,而是采用流水线传输。流水线传输就是发送方可连续发送多个分组,不必每发送完一个分组就停下来等待对方的确认。这样可以使信道上一直有数据不间断地传送,流水线传输中可能会遇到差错,解决差错的两种基本方法是回退 N 步和选择重传。
回退 N 步协议
在回退 N 步即 GBN 协议中,允许发送方发送多个分组而不需要等待确认。在 GBN 中发送方看到的序号可以分为四个范围,已经发送且被确认的的序号、已经发送还未确认的序号、允许发送但还未发送的序号和不允许发送的序号。其中已经发送但还未确认的序号和允许发送但还未发送的序号可以被看作一个长度为 N 的窗口,随着协议的运行该窗口在序号空间向前滑动,因此 GBN 协议也被称为滑动窗口协议。
GBN 发送方必须响应三种类型的事件:
-
上层的调用 当上层调用发送方法时,发送方首先检查发送窗口是否已满,即是否有 N 个已发送但未确认的分组。如果窗口未满,则产生一个分组并将其发送并更新相应变量,如果窗口已满,发送方指需将数据返回给上层,隐式说明该窗口已满。实际实现中,发送方更可能缓存而不是立即发送这些数据,或者使用同步机制允许上层在仅当窗口不满时才调用发送方法。 -
收到一个 ACK 在 GBN 协议中,对序号为 n 的分组确认采用累积确认的方式,对按序到达的最后一个分组发送确认,表明接收方已经正确接收到序号为 n 的以前且包括 n 在内的所有分组。例如发送了序号为 1~5 的五个分组,除了第三个全部收到了,那么确认序号就是 2。 -
超时事件 回退 N 步的名字来源于出现丢失和时延过长时发送方的行为,就像在停止等待协议中那样,如果超时,发送方会重传所有已经发送但还未确认过的分组。如果收到一个 ACK,但仍有已发送但未确认的分组,则计时器也会重新启动。
在 GBN 协议中,接收方丢弃所有失序分组,即使是正确接收的也要丢弃,这样做的理由是接收方必须按序将数据交付给上层。这种做法的优点是接收缓存简单,即接收方不需要缓存任何失序分组。不过丢弃一个正确失序分组的缺点是随后对该分组的重传也许也会错误,而导致更多的重传。
选择重传协议
GBN 协议潜在地允许用多个分组填充流水线,因此避免了停止等待协议中的信道利用问题,但是 GBN 本身也存在性能问题,单个分组的差错就能引起 GBN 重传大量分组,许多分组根本没有重传必要。随着信道差错率的增加,流水线会被不必要重传的分组所充斥。
选择重传即 SR 协议,通过让发送方仅重传那些它怀疑在接收方出错的分组而避免不必要的重传。这种个别的、按需重传,要求接收方逐个确认正确接收的分组,再次用窗口长度 N 来限制流水线中未完成和未被确认的分组数。与 GBN 不同的是,发送方已经收到了窗口中对某些分组的 ACK。
接收方将确认一个正确接收的分组,不管是否按序。失序分组将被缓存直到所有丢失分组都收到,这时才可以将一批分组按序交付上层。
TCP 可靠原理
TCP 的可靠传输包含很多机制,例如使用检验和来检测一个传输分组中的比特错误、使用定时器来用于超时重传一个分组、使用序号来检测丢失的分组和冗余副本、使用确认来告诉发送方确认的分组信息、使用否定确认来告诉发送方某个分组未被正确接收。
TCP 的发送方仅需维持已发送过但未被确认的字节的最小序号和下一个要发送的字节的序号,从这种角度看 TCP 更像一个 GBN 协议。但是 TCP 和 GBN 有一些显著的区别,许多 TCP 实现会将正确接收但失序的报文段缓存起来。当分组 n 丢失时,GBN 会重传 n 之后的所有分组,但是 TCP 至多只会重传分组 n。对 TCP 提出的一种修改意见是选择确认,它允许 TCP 接收方有选择地确认失序报文段,而不是累积地确认最后一个正确接收的有序报文段,从这个角度看 TCP 又像 SR 协议。因此 TCP 的差错恢复机制是一种 GBN 和 SR 的结合体。
除此之外,TCP 还使用流量控制和拥塞控制来保证可靠性。
滑动窗口
滑动窗口以字节为单位。发送端有一个发送窗口,窗口中的序号是允许发送的序号,窗口的后沿是已经发送并且确认的序号,窗口的前沿是不允许发送的序号。窗口的后沿可能不动(代表没有收到新的确认),也有可能前移(代表收到了新的确认),但是不会后移(不可能撤销已经确认的数据)。窗口的前沿一般是向前的,也有可能不动(表示没有收到新的请求或对方的接收窗口变小),也有可能收缩,但 TCP 强烈不建议这么做,因为发送端在收到通知前可能已经发送了很多数据,此时如果收缩窗口可能会产生错误。
滑动窗口的状态需要3个指针p1,p2 和 p3。p1 之前的序号表示已经发送并且确认的序号,p1~p2 的序号表示已经发送但还没有确认的序号,p2~p3 表示允许发送的序号,也叫可用窗口,p1~p3 表示发送窗口,p3 之后的序号表示不可发送的序号。
发送缓存用来暂时存放发送应用程序传给发送方 TCP 准备发送的数据和已经发送但还没确认的数据。接收缓存用来暂时存放按序到达的但尚未被应用程序读取的数据以及未按序到达的数据。
注意三点:① 发送窗口根据接收窗口设置,但并不总是一样大,还要根据网络的拥塞情况调整。② 对于不按序到达的数据,TCP 通常存放在接收窗口,等到字节流缺少的字节收到后再按序交付上层应用程序。③ 接收方必须有累积确认功能,可以减小传输开销,可以在合适的时候发送确认,也可以在自己有数据需要发送时捎带确认。但是接收方不能过分推迟发送确认,不能超过0.5秒。
流量控制
如果某个应用程序读取数据的速度较慢,而发送方发送得太多、太快,发送的数据就会很容易使连接的接收缓存溢出,TCP 为它的应用程序提供了流量控制以消除发送方使接收方缓存溢出的可能性。流量控制是一个速度匹配服务,即发送方的发送速率与接收方的应用程序读取速率相匹配。
TCP 通过让发送方维护一个接收窗口的变量来提供流量控制。通俗地说,接收窗口用于给发送方一个指示,该接收方还有多少可用的缓存空间,因此方法方的发送窗口不能超过接收方给出的接收窗口的数值。因为 TCP 是全双工通信,在连接两端的发送方都各自维护一个接收窗口。
当接收窗口 rwnd 减小到 0 时,就不再允许发送方发送数据了。但是可能存在一种情况,当发生了零窗口报文段不久后,发送方的接收缓存又有了一些存储空间,因此又发生了新的报文说明自己的接收窗口大小,但是这个报文可能会在传输过程中丢失。接收方就会一直等待发送方的非零窗口通知,而发送方也一直在等待接收方发送数组,形成一种死锁的状态。为了解决这个问题,TCP 为每一个连接设有一个持续计时器,只要 TCP 连接的一方收到对方的零窗口通知就启动该计时器,到期后发送一个零窗口探测报文,如果仍为 0 就重新设置计时器的时间,如果对方给出了新的窗口值就可以解决可能出现的死锁问题。
还有一种问题叫做糊涂窗口综合症,当接收方处理接收缓冲区数据很慢时,就会使应用进程间传送的有效数据很小, 极端情况下有效数据可能只有 1 字节但传输开销却有 40 字节(20字节的 IP 头以及 20 字节的 TCP 头) ,导致网络效率极低。为了解决这个问题,可以让接收方等待一段时间,使得接收缓存有足够的空间容纳一个最长报文段或者等到接收缓存已有一半的空闲空间。发送方也不要发送太小的报文,而是把数据积累成足够大的报文或达到接收方缓存空间的一半时才发送。
拥塞控制
网络中对资源需求超过了资源可用量的情况就叫做拥塞。当吞吐量明显小于理想的吞吐量时就出现了轻度拥塞,当吞吐量随着负载的增加反而下降时,网络就进入了拥塞状态。当吞吐量降为 0 时,网络已无法正常工作并陷入死锁状态。拥塞控制就是尽量减少注入网络的数据,减轻网络中的路由器和链路的负担。拥塞控制是一个全局性的问题,它涉及网络中的所有路由器和主机,而流量控制只是一个端到端的问题,是两个端点之间通信量的控制。
根据网络层是否为运输层拥塞控制提供显式帮助可以将拥塞控制的方法区分为两种:端到端拥塞控制和网络辅助的拥塞控制。TCP 使用端到端的拥塞控制,因为 IP 层不会向端系统提供显式的网络拥塞反馈。TCP 所采取的方法是让每一个发送方根据所感知到的网络拥塞程度来限制其向连接发送数据的速率。如果一个 TCP 发送方感知到它到目的地之间的路径上没什么拥塞则会增加发送速率,如果发送方感知到拥塞就会降低其发送速率。限制发送速率是通过拥塞窗口来实现的,它对发送方能向网络中发送流量的速率进行了限制。判断拥塞是通过超时或者连续接收到 3 个冗余 ACK 实现的。
TCP 的拥塞控制算法主要包括了慢启动、拥塞避免和快恢复。慢启动和拥塞避免是 TCP 的强制部分,差异在于对收到的 ACK 做出反应时 cwnd 增加的方式,慢启动比拥塞避免要更快地增加 cwnd 的长度。快恢复是推荐部分,对 TCP 发送方不是必需的。
1. 慢启动
在慢启动状态,拥塞窗口 cwnd 的值以一个 MSS 最大报文段开始并且每当传输的报文段首次被确认就增加一个 MSS。因此每经过一个 RTT 往返时间,拥塞窗口就会翻倍,发送速率也会翻倍。因此 TCP 的发送速率起始很慢,但是在慢启动阶段以指数增长。
结束慢启动有三种情况:① 如果存在一个超时指示的丢包事件,即发生了拥塞,TCP 发送方就会将 cwnd 设置为 1 并重新开始慢启动过程。它还将慢启动阈值设置为 cwnd/2,即检测到拥塞时将慢启动阈值设置为拥塞窗口的一半。② 当拥塞窗口达到慢启动阈值时就会结束慢启动而进入拥塞避免模式。③ 最后一种结束慢启动的方式是,如果检测到三个冗余的 ACK,TCP 就会执行快重传并进入快恢复状态。
2. 拥塞避免
一旦进入拥塞避免状态,cwnd 的值大约是上次遇到拥塞时的值的一半,即距离拥塞可能并不遥远。因此 TCP 无法再每经过一个 RTT 就将 cwnd 的值翻倍,而是采用一种较为保守的方法,每个 RTT 后只将 cwnd 的值增加一个 MSS。这能够以几种方式完成,一种通用的方法是发送方无论何时收到一个新的确认,都将 cwnd 增加一个 MSS。
当出现超时时,TCP 的拥塞避免和慢启动一样,cwnd 的值将被设置为 1,并且将慢启动阈值设置为 cwnd 的一半。
3. 快恢复
有时候个报文段丢失,而网络中并没有出现拥塞,如果使用慢启动算法就会降低传输效率。这时应该使用快重传来让发送方尽早知道出现了个别分组的丢失,快重传要求接收端不要等待自己发送数据时再捎带确认,而是要立即发送确认。即使收到了乱序的报文段后也要立即发出对已收到报文段的重复确认。当发送方连续收到三个冗余 ACK 后就知道出现了报文段丢失的情况,会立即重传并进入快恢复状态。
在快恢复中,会调整慢启动阈值为 cwnd 的一半,并进入拥塞避免状态。
TCP 连接和释放机制
三次握手
TCP 是全双工通信,任何一方都可以发起建立连接的请求,假设 A 是客户端,B 是服务器。
初始 A 和 B 均处于 CLOSED 状态,B 会创建传输进程控制块 TCB 并进入 LISTEND 状态,监听端口是否收到了 TCP 请求以便及时响应。
当 A 要发生数据时就向 B 发送一个连接请求报文,TCP 规定连接请求报文的 SYN=1,ACK=0,SYN 不可以携带数据,但要消耗一个序号,假设此时 A 发送的序号 seq 为 x。发送完之后 A 就进入了 SYN-SENT 同步已发送状态。
当 B 收到 A 的连接请求报文后,如果同意建立连接就会发送给 A 一个确认连接请求报文,其中 SYN=1,ACK=1,ack=x+1,seq=y,ack 的值为 A 发送的序号加 1,ACK 可以携带数据,如果不携带的话则不消耗序号。发送完之后,B进入 SYN-RCVD 同步已接收状态。
当 A 收到 B 的确认连接请求报文后,还要对该确认再进行一次确认,报文的 ACK=1,ack=y+1,seq=x+1,发送后 A 进入 ESTABLISHED 状态,当 B 接收到该报文后也进入 ESTABLISHED 状态,客户端会稍早于服务器端建立连接。
三次握手的原因主要有两个目的,信息对等和防止超时。
从信息对等的角度看,双方只有确定 4 类信息才能建立连接,即 A 和 B 分别确认自己和对方的发送和接收能力正常。在第二次握手后,从 B 的角度看还不能确定自己的发送能力和对方的接收能力,只有在第三次握手后才能确认。
三次握手也是防止失效连接突然到达导致脏连接,网络报文的生存时间往往会超过 TCP 请求超时时间,A 的某个超时连接请求可能会在双方释放连接之后到达 B,B 会误以为是 A 创建了新的连接请求,然后发送确认报文创建连接。因为 A 机器的状态不是 SYN_SENT,所以直接丢弃了 B 的确认数据。如果是两次握手,连接已经建立了,服务器资源被白白浪费。如果是三次握手,B 由于长时间没有收到确认信息,最终超时导致创建连接失败,因此不会出现脏连接。
四次挥手
当 A 已经没有要发送的数据时就会释放连接,会向 B 发送一个终止连接报文,其中 FIN=1,seq=u,u 的值为之前 A 发送的最后一个序号+1。发送完之后进入 FIN-WAIT-1 状态。
B 收到该报文后,发送给 A 一个确认报文,ACK=1,ack=u+1,seq=v,v 的值为 B 之前发送的最后一个序号+1。此时 A 进入了FIN-WAIT-2 状态,B 进入了 CLOSE-WAIT 状态,但连接并未完全释放,B 会通知高层的应用层结束 A 到 B 方向的连接,此时 TCP 处于半关闭状态。
当 B 发送完数据后准备释放连接时,就向 A 发送连接终止报文,FIN=1,同时还要重发ACK=1,ack=u+1,seq=w,seq 不是 v 的原因是在半关闭状态 B 可能又发送了一些数据,之后 B 进入 LAST-ACK 状态。
A 收到连接终止报文后还要再进行一次确认,确认报文中 ACK=1,ack=w+1,seq=u+1。发送完之后进入 TIME-WAIT 状态,等待 2MSL之后进入 CLOSED 状态,B 收到该确认后进入 CLOSED 状态,服务器端会稍早于客户端释放连接。
四次挥手的原因
第一点原因是为了保证被动关闭方可以进入 CLOSED 状态。MSL 是最大报文段寿命,等待 2MSL 可以保证 A 发送的最后一个确认报文能被 B 接收,如果该报文丢失,B 没有收到就会超时重传之前的 FIN+ACK 报文,而如果 A 在发送确认报文后就立即释放连接就无法收到 B 超时重传的报文,因而也不会再一次发送确认报文段,B 就无法正常进入 CLOSED 状态。
第二点原因是 2MSL 时间之后,本连接中的所有报文就都会从网络中消失,可以防止已失效连接的请求数据包与正常连接的请求数据包混淆而发生异常。
除此之外,TCP 还设有一个保活计时器,用于解决客户端主机故障的问题,服务器每收到一次客户的数据就重新设置保活计时器,时间为 2 小时。如果 2 小时内没有收到就间隔 75 秒发送一次探测报文,连续 10 次都没有响应后就关闭连接。
大量 TIME-WAIT 的原因、导致的问题、处理
在高并发短连接的 TCP 服务器上,服务器处理完请求后立刻主动正常关闭连接,这个场景下会出现大量 socket 处于 TIME-WAIT 状态。
TIME-WAIT 状态无法真正释放句柄资源,socket 使用的本地端口在默认情况下不能再被使用,会限制有效连接数量,成为性能瓶颈。
可以调小 tcp_fin_timeout 的值,将 tcp_tw_reuse 设为 1 开启重用,将 tcp_tw_recycle 设为 1 表示开启快速回收。
TCP 和 UDP 的区别
TCP 是面向连接的,而 UDP 是无连接的,发送数据之前不需要建立连接,减少了开销和发送数据之前的时延。
TCP 保证数据的可靠传输,UDP 使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的连接状态。
TCP 是面向字节流的,UDP 是面向报文的,发送方的 UDP 对应用程序交下来的报文,在添加首部后就向下交付 IP 层。UDP 对应用层交下来的报文既不拆分也不合并,而是保留这些报文的边界。如果报文太长,IP 层在传送时可能需要分片,如果报文太短,会使 IP 数据报首部的相对长度太大,都会降低 IP 层的效率。
TCP 有拥塞控制,UDP 没有拥塞控制,因此网络中出现的拥塞不会降低源主机的发送速率。这对某些实时应用很重要,很多实时应用如 IP 电话、实时视频会议等要求源主机以恒定的速率发送数据,并且允许在网络发生拥塞时丢失一些数据,但却不允许网络有太大的时延,UDP 正好适合这种要求。
TCP 是点到点之间的一对一通信,UDP 支持一对一、一对多和多对多的交互通信。
UDP 的首部开销很小,只有 8 字节,相比 TCP 的 20 字节要短。
HTTP
HTTP 概况
HTTP 即超文本传输协议,是 Web 的应用层协议。HTTP 由两个程序实现,一个客户程序和一个服务器程序,客户程序和服务器程序运行在不同的端系统中,通过交换 HTTP 报文进行会话。HTTP 定义了这些报文的结构以及客户和服务器进行报文交换的方式,当用户请求一个 Web 页面时,浏览器向服务器发出对该页面中所包含对象的 HTTP 请求报文,服务器接收到请求并用包含这些对象的 HTTP 响应报文进行响应。
HTTP 使用 TCP 作为它的支撑运输协议,HTTP 客户首先发起一个与服务器的 TCP 连接,一旦连接建立,该浏览器和服务器进程就可以通过套接字访问 TCP。客户端的套接字接口是客户进程与 TCP 连接之间的门,服务器端的套接字接口则是服务器进程与 TCP 连接之间的门。客户向它的套接字接口发送 HTTP 请求报文并从它的套接字接口接收 HTTP 响应报文,类似的,服务器从它的套接字接口接收 HTTP 请求报文并向它的套接字接口发送 HTTP 响应报文。一旦客户向它的套接字接口发送一个 HTTP 请求报文,该报文就脱离了客户控制并进入 TCP 的控制,TCP 为 HTTP 提供可靠的数据传输服务,因此一个客户进程发出的每个 HTTP 请求报文最终都能完整地到达服务器,服务器进程发出地每个 HTTP 响应报文最终也可以完整地到达客户。这里体现了分层体系结构的优点,HTTP 协议不需要担心数据丢失,也不需要关注 TCP 从网络的数据丢失和乱序中如何恢复。
HTTP 是一种无状态的协议,服务器向客户发送被请求的文件,而不存储任何关于该客户的状态信息。假如某个客户在短时间内连续两次请求同一个对象,服务器并不会因为刚刚为该客户做出了响应就不再响应,而是重新进行响应。
非持续连接和持续连接
依据每个请求/响应对经过一个单独的 TCP 连接还是相同的 TCP 连接发送,可以将连接划分为非持续连接和持续连接。HTTP 默认使用持续连接,但是也可以配置成使用非持续连接。
非持续连接
使用非持续连接时,从服务器向客户传送一个包含了一个 HTML 文件和 10 个 JPG 对象的 Web 页面步骤:
① HTTP 客户进程在端口号 80 发起一个到服务器的 TCP 连接,并经它的套接字向服务器发送一个 HTTP 请求报文。② HTTP 服务器进程经它的套接字接收请求报文,从其存储器中检索出请求对象,在一个 HTTP 响应报文中封装对象,并通过套接字向客户发送响应报文。③ HTTP 服务器进程通知 TCP 断开该 TCP 连接,直到 TCP 确认客户已经完整接收到响应报文才会实际断开连接。④ HTTP 客户接收到响应报文,客户从报文中提取出 HTML 文件,得到多个 JPG 图像的引用,并对每个引用的 JPG 图像对象重复前三个步骤。
每个 TCP 连接会在服务器发送一个对象后关闭,即该连接并不为其他的对象而持续下来。每个 TCP 连接只传输一个请求报文和一个响应报文,假如请求一个 HTML 文件和其中包括的 10 个 JPG 图像就要产生 11 个 TCP 连接。
在非持续连接中,每次请求文件到接收响应大约需要花费两个 RTT 加上服务器传输文件的时间,RTT 就是往返时间,指一个短分组从客户到服务器然后再返回客户所发送的时间。其中三次握手的前两个部分占用一个 RTT,三次握手的第三个确认部分向服务器发送了请求报文,服务器接收到之后做出响应,这用去了另一个 RTT。
持续连接
非持续连接有很多缺点。第一,必须为每个请求的对象建立和维护一个新的连接,对于每个连接,在客户和服务器中都要分配 TCP 的缓冲区和保持 TCP 变量,这给 Web 服务器带来了很大负担。第二,每一个对象需要消耗两倍的 RTT,一个用于创建 TCP,一个用于请求和接收对象。
在 HTTP1.1 中使用了持续连接,服务器在发送响应后保持该 TCP 连接打开。在相同的客户与服务器之间,后续的请求和响应报文能够通过相同的连接进行传送。在使用持续连接的情况下,请求一个完整的 Web 页面可以使用单个持续的 TCP 连接,例如之前所说的包含一个 HTML 文件和 10 个 JPG 对象的 Web 页面就只需要一个 TCP 连接而不是 11 个。
HTTP 报文格式
HTTP 报文有两种,分为请求报文和响应报文。
请求报文
HTTP 请求报文的第一行叫做请求行,其后继的行叫做首部行。请求行有三个字段,包括方法、URL 和 HTTP 版本。方法包括了 GET、POST、HEAD、PUT 和 DELETE 等。绝大部分的 HTTP 请求报文使用 GET 方法,当使用 GET 方法时,在 URL 字段中会带有请求对象的标识。
首部行指明了对象所在的主机,其实已经存在 TCP 连接了,但是还需要首部行提供主机信息,这时 Web 代理高速缓存所要求的。通过包含 Connection:close 的首部行,可以告诉服务器不要麻烦地使用持续连接,它要求在发送完响应后就关闭连接。User-agent 可以用来指明用户代理,即向服务器发送请求的浏览器类型,服务器可以有效地为不同类型的用户代理发送实际相同对象的不同版本。
在首部行之后有一个空行,后面跟着的是实体。使用 GET 方法时实体为空,而使用 POST 方法时才会使用实体。当用户提交表单时,HTTP 客户通常使用 POST 方法,使用 POST 方法时用户仍可以向服务器请求一个 Web 页面,但 Web 页面的特定内容依赖于用户在表单字段中输入的内容。如果使用 POST 方法,则实体中包含的就是用户在表单字段的输入值。表单不是必须使用 POST 方法,也可以使用 GET。
HEAD 方法类似于 GET,当服务器收到一个使用 HEAD 方法的请求时,将会用一个 HTTP 报文进行响应,但是并不返回请求对象。通常开发者使用 HEAD 方法进行调试跟踪。PUT 方法常用于上传对象到指定的 Web 服务器上指定的目录,DELETE 方法允许用户或应用程序删除 Web 服务器上的对象。
响应报文
响应报文包括状态行、首部行和实体。状态行有三个字段,协议版本、状态码和对应的状态信息。实体是报文的主要部分,即所请求的对象本身。
服务器通过首部行来告诉浏览器一些信息。 Connection:close 可以告诉客户发送完报文后将关闭该 TCP 连接。Date 是首部行指示服务器发送响应报文的日期和时间,这个时间不是对象创建或修改的时间,而是服务器从它的文件系统中检索到该对象,将该对象插入响应报文并发送的时间。Server 指明了服务器的类型,类似于请求报文中的 User-agent 。
状态码及其相应的短语指示了请求的结果,一些常见的状态码和相关短语如下:
状态码 | 短语 | 含义 |
---|
200 | OK | 成功响应 | 301 | Moved Permanently | 请求的对象已经被永久转移了,新的 URL 定义在响应报文的 Location 首部行,客户将自动获取新的 URL。 | 302 | Found | 与301类似,但资源只是临时被移动,客户端应继续使用原有 URL。 | 400 | Bad Request | 一个通用的差错代码,标识该请求不能被服务器理解。 | 401 | Unauthorized | 未认证,缺乏相关权限。 | 402 | Payment Required | 保留,将来使用 | 403 | Forbidden | 服务器理解客户端的请求,但是拒绝执行。 | 404 | Not Found | 被请求的文档不在服务器上,有可能因为请求 URL 出错。 | 405 | Method Not Allowed | 客户端中请求的方法被禁止,例如限制 POST 方式但使用了 GET 访问。 | 500 | Internal Server Error | 服务器内部错误,无法完成请求。 | 501 | Not Implemented | 服务器不支持请求的功能,无法完成请求。 | 502 | Bad Gateway | 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应。 | 503 | Service Unavailable | 由于超载或系统维护,服务器暂时的无法处理客户端的请求。 | 504 | Gateway Timeout | 充当网关或代理的服务器,未及时从远端服务器获取请求。 | 505 | HTTP Version Not Supported | 服务器不支持请求报文使用的 HTTP 协议版本。 |
cookie
HTTP 的无状态性简化了服务器的设计,并且提高了 Web 服务器的性能,使其可以同时处理大量的 TCP 连接。但是一个 Web 站点通常希望能够识别用户,可能是为了限制用户的访问,也可能为了把内容与用户身份关联起来,为此 HTTP 使用了 cookie,cookie 是一种客户端的会话技术,允许站点对用户进行追踪。
cookie 技术有四个组件
① 在 HTTP 响应报文中的一个 cookie 首部行。② 在 HTTP 请求报文中的一个 cookie 首部行。③ 在用户端系统中保留有一个 cookie 文件,并由用户的浏览器关联。④ 位于 Web 站点的一个后端数据库。cookie 的工作流程:当客户通过浏览器第一次访问某个站点时,该 Web 站点将产生一个唯一识别码,并以此作为索引在它的后端数据库中产生的一个表项。接下来服务器会用一个包含 Set-cookie 首部的 HTTP 响应报文对浏览器进行相应,当浏览器收到后将其添加到自己管理的 cookie 文件中,在下次访问该站点时,请求报文的首部行中就会包括这个识别码,尽管浏览器不知道客户是谁,但是可以确定是同一个客户进行了访问。
cookie 和 session 的区别
① cookie 只能存储 ASCII 码字符串,而 session 则可以存储任何类型的数据,因此在考虑数据复杂性时首选session。② session 存储在服务器,而 cookie 存储在客户浏览器中,容易被恶意查看。如果非要将一些隐私数据存在 cookie 中,可以将 cookie 值进行加密,然后在服务器进行解密。
Web 缓存
Web 缓存器也叫代理服务器,它是能够代表初始 Web 服务器来满足 HTTP 请求的网络实体。Web 缓存器有自己的磁盘存储空间,并在存储空间中保存最近请求过的对象副本。可以配置用户的浏览器,使得用户所有的 HTTP 请求首先指向 Web 缓存器。客户通过 Web 缓存器请求对象的步骤如下:
① 浏览器创建一个到 Web 缓存器的 TCP 连接,并向 Web 缓存器中的对象发送一个 HTTP 请求。② Web 缓存器进行检查,查看本地是否存储了该对象副本。如果有,Web 缓存器就向客户浏览器用 HTTP 响应报文返回该对象。③ 如果 Web 缓存器中没有该对象,它就打开一个与该对象的初始服务器的 TCP 连接,Web 缓存器在这个连接上发送一个请求并接受响应。④ Web 缓存器接收到响应后,在本地存储空间存储一份副本,并向客户的浏览器用 HTTP 响应报文发送该副本。
Web 缓存器既是服务器又是客户,当它接受浏览器的请求并响应时,它是一个服务器,当他向初始服务器发出请求并接收响应时,它是一个客户。在因特网上部署 Web 缓存器有两个原因,首先,Web 缓存器可以大大减少对客户请求的响应时间,特别是客户与初始服务器之间的带宽远低于客户与 Web 缓存器之间的带宽时更是如此。其次,Web 缓存器可以大大减少一个机构的接入链路到因特网的通信量,通过减少通信量,机构就不必基于增加带宽,可以降低费用。
输入一个 url 发生的事
① 分析 url
判断输入的 url 是否合法,如果不合法浏览器会使用默认的搜索引擎进行搜索。如果输入的是一个域名,默认会加上一个 http 前缀。
② DNS 查询
检查浏览器的 DNS 缓存,检查本地 hosts 文件的缓存,如果没有会向本地 DNS 服务器发送请求。
主机向本地 DNS 服务器发起请求是递归查询,如果找到则返回,否则会向根 DNS 查询。
根 DNS 查询是迭代查询,没有域名和 ip 的对应关系,而是告知可以查询的域名服务器地址。
本地 DNS 向得到的域名服务器发出请求,收到一个域名和 ip 关系,把结果返回给用户,并把结果保存到缓存中。
③ TCP 建立连接
拿到 ip 地址后,通过 TCP 的三次握手建立连接,按照协议规定的格式发送 HTTP 请求报文。
④ 处理请求
服务器收到 HTTP 请求报文后进行响应,主进程进行监听,创建子进程处理,先判断是否是重定向,如果是重定向则返回重定向地址。如果是静态资源则直接返回,否则通过 REST URL 在代码层面处理返回结果,最后返回 HTTP 响应报文。
⑤ 接收响应
浏览器收到 HTTP 响应报文后进行解析,首先查看响应报文在状态行的状态码,根据不同的状态码做不同的事,解析 HTML、CSS、JS 等文件。构建 DOM 树,渲染树,重绘,将像素发送 GPU 进行渲染,最后将渲染结果返回给用户并进行缓存。
⑥ TCP 断开连接
通过 TCP 的四次挥手断开连接,如果是 HTTP1.1 则会将连接保持一小段时间。
HTTPS
HTTP 存在的问题
HTTP 没有密码加密,无法保证通信内容不被窃听,攻击者可以截取客户发送的数据并得到他的信息。
HTTP 没有报文完整性验证,无法确保通信内容在传输过程中不被改变,攻击者可以篡改客户通信内容。
HTTP 没有身份鉴别,无法让通信双方确认对方的身份,攻击者可以伪装成客户或者服务器。
加密原理
HTTPS 即 HTTP over SSL,在 HTTP 传输上增加了 SSL 安全性服务。SSL 是安全套接字层,通过采用机密性、数据完整性、服务器鉴别以及客户鉴别来强化 TCP,主要用于为发生在 HTTP 之上的事务提供安全性。SSL 会对数据进行加密并把加密数据送往 TCP 套接字,在接收方,SSL 读取 TCP 套接字中的数据并解密,然后把数据交给应用层。HTTPS 采用混合加密机制,使用非对称加密传输对称密钥来保证传输过程的安全性,之后使用对称加密进行通信来保证通信过程的效率。
HTTPS 的传输过程主要分为两部分:通过 SSL 握手建立安全的 HTTPS 通道和在安全的通道上进行数据传输,SSL 握手的步骤如下:
① 客户发送它支持的密码算法列表,以及一个客户的不重数,不重数就是在一个协议的生存期只使用一次的数。
② 服务器从该列表中选择一种对称加密算法(例如 AES),一种公钥加密算法(例如 RSA)和一种报文鉴别码算法。服务器把它的选择以及证书和一个服务器不重数返回给客户。
③ 客户通过 CA 提供的公钥验证该证书,验证成功后提取服务器的公钥,生产一个前主密钥 PMS,用服务器的公钥加密该 PMS,并将加密的 PMS 发送给服务器。
④ 客户和服务器独立地从 PMS 和不重数中计算出仅用于当前 SSL 会话的主密钥 MS,然后该 MS 被切片以生成两个密码和两个报文鉴别码密钥。自从以后,客户和服务器之间发送的所有报文均被加密和鉴别(使用报文鉴别码)。
⑤ 客户和服务器分别发送所有握手报文的一个报文鉴别码。这一步是为了使握手免受篡改危害,在第一步中客户提供的算法列表是以明文形式发送的,因此可能被攻击者截获并删除较强的算法。当客户发送一个级联它以及发送和接收的所有握手报文的报文鉴别码,服务器能够比较这个报文鉴别码和它已经接受和发送的握手报文的报文鉴别码,如果不一致就终止连接。类似的,客户也可以通过服务器发送的报文鉴别码来检查一致性。
第一步和第二步中的不重复数用于防止重放攻击,每个 TCP 会话使用不同的不重复数就可以使加密密钥不同,当收到重放的 SSL 记录时,该记录无法通过完整性检查,假冒的电子事务不会成功。
当结束 SSL 会话时,需要在类型字段中指出该记录是否是用于终止 SSL 会话的。通过包含这样一个字段,如果客户或服务器在收到一个关闭 SSL 记录之前突然收到了一个 TCP FIN,就知道遭受了截断攻击。
网络安全
网络安全主要探讨的问题是攻击者如何攻击计算机网络,以及如何防御这些攻击,或者如何事先预防这样的攻击。
网络攻击
计算机网络面临的威胁主要有被动攻击和主动攻击。
被动攻击指攻击者从网络上窃听他人的通信内容,也叫截获。在被动攻击中,攻击者只是观察和分析某一协议数据单元 PDU 而不干扰信息流。攻击者可以通过观察 PDU 的协议控制信息部分,了解正在通信的协议的地址和身份,通过研究 PDU 的长度和发送频度,了解所交换的数据的某种性质。这种攻击又叫做流量分析。
主动攻击包括:
-
篡改 攻击者篡改网络上传输的报文,包括彻底中断传送的报文,甚至把完全伪造的报文发给接收端,这种攻击方式也叫做更改报文流。 -
恶意程序 ① 计算机病毒,能够传染其他程序的程序,主要通过修改其他程序来把自身或自身的变种复制进去完成。② 计算机蠕虫,通过网络通信能把自己从一个结点发往另一个节点并且自动启动运行的程序。③ 特洛伊木马,它执行的功能并非声称的功能而是恶意程序,例如一个编译程序除了完成编译任务外还偷偷地复制源程序。④ 逻辑炸弹,当运行环境满足某种特殊条件时就会执行特殊功能的程序,例如当日期为 22 号且为周三的时候就会删除所有文件。⑤ 后门入侵,指利用系统实现中的漏洞通过网络入侵系统。⑥ 流氓软件,一种未经用户同意就在用户计算机上安装并损害用户利益的软件。 -
拒绝服务DoS DoS 攻击使得网络、主机或其他基础设施部分不能由合法用户使用。Web 服务器、电子邮件服务器、DNS 服务器和机构网络都能够成为 DoS 攻击的目标。大多数 DoS 攻击属于以下三种情况:① 弱点攻击,指向一台目标主机上运行的易受攻击的应用程序或操作系统发送制作精细的报文,如果适当顺序的多个分组发送给一个易受攻击的应用程序或操作系统,该服务器可能会停止运行甚至崩溃。② 带宽洪泛,指攻击者向目标主机发送大量的分组,分组数量之多使得目标的接入链路变得阻塞,使合法的分组无法到达服务器。③ 连接洪泛,指攻击者在目标主机中创建大量的半开或全开 TCP 连接,主机因这些伪造的连接而陷入困境,并停止接受合法的连接。 -
ARP欺骗 在使用以太网交换机的网络中,攻击者向某个以太网交换机发送大量的伪造源 MAC 地址,以太网交换机收到这样的帧就把虚假的 MAC 源地址填入到交换表中,由于伪造的数量很大很快就填满了表,导致以太网交换机无法正常工作。
对于被动攻击可以采用各种数据加密技术,对付主动攻击则需要将加密技术与适当的鉴别技术相结合。
安全的计算机网络具有以下特性:
-
机密性 仅有发送方和希望的接收方能够理解报文传输的内容,因为窃听者可以截获报文,这要求报文必须进行加密,使截取而都报文无法被截获者理解。为了使网络具有保密性,需要使用各种密码技术。 -
报文完整性 通信内容在传输过程中需要被确保未被恶意篡改或意外改动。 -
端点鉴别 发送方和接收方都应该能证实通信过程中的另一方,以确信通信的另一方确实具有其声称的身份。在实际应用中,报文完整性和端点鉴别往往是不可分割的,因为假设通过了端点鉴别保证了通信双方的身份却没有通过报文鉴别保证报文的完整性是没有意义的。 -
运行安全性 几乎所有机构都有与互联网相连的网络,这些网络都因此具有潜在的安全问题。需要通过访问控制来确保网络的安全性,防火墙位于机构和公共网络之间,控制接入和来自网络的分组;入侵检测系统指需深度分组检查任务,向网络管理员发出有关可疑活动的警告。
密码技术
密码技术使发送方可以伪装数据,接收方需要从伪装的数据中恢复出初始数据,而入侵者不能从截获到的数据中获得任何信息。报文的最初形式被称为明文,在使用加密算法加密后得到的加密报文被称为密文。密码体制分为两种,对称密钥密码体制和公开密钥密码体制。
对称密钥密码体制使用相同的加密密钥和解密密钥,对称加密的运算速度快,但是安全性差,因为在密钥传输的过程中可能会被截获。数据加密标准 DES 属于对称密码密钥,这种密码的保密性仅仅取决于对密钥的保密,而算法是公开的,之后被更加安全的高级加密标准 AES 所取代。
公开密钥密码体制使用公钥进行加密,私钥进行解密,其中公钥是任何人都可以得知的,而私钥是通信双方所独有的。非对称加密的运算速度慢,但是安全性好。最常见的公钥加密算法是 RSA,它使用两个大素数 p 和 q 来生成密钥,p 和 q 的值越大,破解的难度就越大,但是执行加密和解密的时间也就越长,RSA 实验室推荐 p 和 q 的乘积为 1024 的数量级。
在使用对称密钥时,由于双方使用同样的密钥,因此在通信信道上可以进行一对一的双向保密通信,每一方既可以用该密钥加密明文并发送给对方,也可以接收密文用同一密钥解密。这种保密通信仅限于持有此密钥的双方。但在使用公开密钥时,在通信信道上可以是多对一的单向保密通信,可以同时有很多客户利用公钥对自己的报文加密后发送给某个服务器,服务器利用其私钥可以对收到的密文一一解密,但如果是反方向则是行不通的,例如在网购时很多客户都向同一个网站发送各自的信用卡信息。
数字签名
数字签名的作用
① **报文鉴别:**接收者能够核实发送者对报文的签名,也就是说接收者可以确认报文发送方的身份。
② **报文完整性:**接收者可以确信收到的数据和发送者发送的完全一样并且没有被篡改过。
③ **不可否认:**发送者事后不能抵赖对报文的签名。
实现原理
有多种实现数字签名的方法,但采用公钥算法要比采用对称密钥算法更容易实现。为了进行签名,会首先用私钥对报文进行 D 运算得到某种不可读的密文,为了核实签名,接收方会利用发送方的公钥进行 E 运算还原出明文。任何人都可以用发送方的公钥还原出明文,因此这种通信方式并不是为了保密,而是为了进行签名和核实签名,即确认发送方的身份。
数字签名实现报文鉴别:除了发送方之外没有人持有其私钥,因此无法产生发送方才能产生的密文。
数字签名保证报文完整性:如果其他人篡改过密文,那么解密出的明文就会不可读,就知道收到的报文被篡改过。
数字签名保证不可否认:如果发送方抵赖发送过报文,接收方可以把初始报文和密文发送给公证的第三者,第三者通过公钥很容易证实发送方确实发送过报文。
公钥认证
攻击者可能会发送使用自己私钥加密的密文和自己的公钥来伪造发送方的身份,该问题通过 CA 解决,发送方在发送数据时也会发送 CA 签署的证书,接收方会利用 CA 的公钥来核对发送方证书的合法性并提取发送方的公钥。
CA 即认证中心,将公钥与特定的实体绑定, 它的职责就是使识别和发行证书合法化。CA 主要有两个作用:① CA 认证一个实体(一个人、一台路由器等)的真实身份。② 一旦 CA 认证了某个实体的身份,CA 会生成一个将其身份和实体的公钥绑定起来的证书,这个证书包含了这个公钥和公钥所有者全局唯一的身份标识信息(例如一个人的名字或一个 IP 地址),由 CA 对这个证书进行数字签名。
报文鉴别
报文鉴别就是鉴别收到的报文确实是发送方发送的,而不是别人伪造或篡改的。数字签名就可以实现报文鉴别,但是数字签名有一个很大的缺点,就是对较长的报文进行数字签名时会使计算机增加非常大的负担,因为需要较长时间的运算。有一种相对简单的报文鉴别方式,就是密码散列函数。在密码学中的散列函数称为密码散列函数,最重要的特点就是:要找到两个不同的报文,它们具有相同的密码散列函数输出,在计算上是不可行的,也就是说密码散列函数实际上是一种单向函数。
使用散列函数进行报文鉴别的原理
通信双方需要共享一个密钥 k ,发送方生成报文 m,用 k 级联 m 生成 m+k,并使用 SHA-1 或 MD5 这样的散列函数计算 m+k 的散列值 h,这个散列值就被称为报文鉴别码 MAC。发送方会将 MAC 附加到报文 m 上,生成一个扩展报文,并将该扩展报文发送给接收方。接收方接到扩展报文后,由于知道共享密钥 k,因此可以计算出报文鉴别码,如果计算出的报文鉴别码和 h 相等就可以得出一切正常的结论。
除了共享密钥,还可以使用公钥加密。发送方可以利用自己的私钥进行散列运算,接收方利用发送方的公钥进行还原。这种方法得到的扩展报文是不为伪造且不可否认的,因为攻击者没有发送方的私钥,无法伪造出发送方发出的报文。
端点鉴别
端点鉴别就是一个实体经过计算机网络向另一个实体证明其身份的过程,实体可以是一个人也可以是一个进程。端点鉴别主要通过鉴别协议 ap 来实现,鉴别协议通常在两个通信实体运行其他协议之前运行。鉴别协议首先建立相互满意的各方标识,仅当鉴别完成之后各方才继续下面的工作。
鉴别协议 ap1.0
发送方直接发送一个报文说明自己的身份,缺陷很大,攻击者可以任意伪造。
鉴别协议 ap2.0
发送方有一个总是用于通信的 IP 地址,接收方可以验证携带鉴别报文的 IP 数据报的源地址和发送方经常使用的 IP 地址是否匹配来进行鉴别。但存在 IP 欺骗的可能性,攻击者也可以伪造源 IP 地址。
鉴别协议 ap3.0
进行鉴别的经典方法是使用秘密口令,口令是鉴别者和被鉴别者之间的一个共享秘密。接收方会要求发送方提供口令来进行验证,但这种方式依旧不是安全的,因为攻击者可能会通过嗅探获得发送方的口令。一种改进想法是对口令进行加密,防止攻击者获得口令,但是这不能解决重放攻击,攻击者可以获取加密口令并不断重放。
鉴别协议 ap4.0
重放攻击主要是由于接收方并不知道此时发送方是否还是活跃的,ap 4.0 主要通过一个不重数来防止重放攻击。不重数就是在一个协议的生存期中只会使用一次的数,是一个不重复使用的大随机数,一旦某协议使用了一个不重数,就永远不会再使用那个数了。接收方会向发送方发送一个不重数,发送方将其加密后发回给接收方,接收方通过验证这个数字来判断发送方是否是活跃的。
安全协议
网络层
网络层的安全协议是 IPsec,它并不是一个单一的协议,而是能够为两个网络实体之间的 IP 数据报提供通信安全的协议族。IPsec 并没有限定用户必须使用的加密和鉴定算法,允许通信双方选择合适的算法和参数,为保证互操作性而包含了一套加密算法,要求所有 IPsec 的实现都必须使用。许多机构都使用 IPsec 来保证虚拟专用网 VPN 的安全性。
IPsec 协议族中有两个主要协议:鉴别首部 AH 协议和封装安全有效载荷 ESP 协议。当某源 IPsec 实体向一个目的实体发发送安全数据报时,它可以使用 AH 或 ESP 协议来实现。AH 提供源鉴别和数据完整性服务,而 ESP 除了这两种服务外还可以提供机密性服务,因此使用要比 AH 广泛许多。使用 AH 或 ESP 的 IP 数据报称为 IP 安全数据报,它可以在两台主机、两台路由器或一台主机和一个路由器之间发送。IP 安全数据报有两种工作方式:① 运输方式,在整个运输层报文段的前后分别加上控制信息再加上 IP 首部,构成 IP 安全数据报。② 隧道方式,在原始的 IP 数据报的前后分别加上控制信息,构成 IP 安全数据报,这种方式使用较多。
运输层
运输层的安全协议主要是 SSL 安全套节字层和 TLS 运输层安全,TLS 是 SSL3.0 的修改版本。SSL 主要作用在端系统的 HTTP 和运输层之间,在 TCP 上建立起一个安全通道,为 TCP 传输的应用层数据提供安全保障。应用层使用 SSL 最多的就是 HTTP,但 SSL 并不是只用于 HTTP,而是可以用于任何应用层的协议,例如 SSL 也可以用于邮件存取的鉴别和数据加密。
SSL 提供的安全性服务包括三种:① 服务器鉴别,允许用户证实服务器的身份,支持 SSL 的客户端通过验证来自服务器的证书来鉴别服务器的身份并取得服务器的公钥。② 客户鉴别,SSL 可选的安全服务,允许服务器验证用户的身份。③ 加密的 SSL 会话,对客户和服务器发送的所有报文进行加密,并检测报文是否被篡改。
防火墙和入侵检测
在计算机网络中,当通信流量进入/离开网络时要执行安全检查、做记录、丢弃或转发,这些工作都有防火墙和入侵检测系统来完成。
防火墙
防火墙是一个硬件和软件的结合体,它将一个机构的内部网络与整个因特网隔离开,内部的属于可信网络,外部的属于不可信网络,允许一些数据分组通过而阻止另一些。它属于一种访问控制技术,通过严格控制进出网络的分组来禁止任何不必要的通信,从而减少潜在侵入的发送,从外部到内部和从内部到外部的所有流量都必须经过防火墙,只有被授权的流量才允许通过,授权与否由本地的安全策略定义,防火墙可以限制对授权流量的访问。
防火墙分为三种:① 基于分组过滤,分组过滤器独立地检查每个数据报,然后基于管理员特定的规则决定该数据报应当允许通过还是丢弃,过滤因素通常包括 IP 源或目的地址、TCP 或 UDP 地源和目的端口、IP 数据报中的协议字段类型等。② 基于状态过滤,利用一张连接表来实际地跟踪 TCP 连接,并使用跟踪信息做出过滤决定。③ 应用程序网关,这是一个应用程序特定的服务器,所有应用程序数据都必须通过它,每种程序都需要一个不同的应用网关。
入侵检测系统 IDS
防火墙不可能阻止所有入侵行为,入侵检测系统作为第二道防线,通过对进入网络的分组进行深度分析与检测发现异常网络行为,并进行报警以便进一步处理。IDS 可以用于检测多种攻击,包括网络映射、端口扫描、DoS 带宽洪泛攻击、病毒和蠕虫等。一个机构可以在它的机构网络中部署一个或多个 IDS 传感器,由于 IDS 不仅需要做深度分组检查,还必须要把每个过往的分组与数以万计的特征进行比较,因此会导致很大的处理量,所以一般都需要多个 IDS 传感器。IDS 系统可以大致分为基于特征的系统和基于异常的系统。
基于特征的 IDS 维护了一个范围广泛的攻击特征数据库,每个特征是一个与入侵活动相关联的规则集,基于特征的 IDS 嗅探通过它的每个分组,将分组中的数据与数据库中的特征进行比较,如果匹配将产生一个警告,该警告能够发送一个电子邮件报文给网络管理员或者网络管理系统。但是基于特征的 IDS 无法应对新型攻击,并且即使与特征匹配时也可能不是一个攻击而因此产生了一个虚假警告。
基于异常的 IDS 会观察正常运行的流量,并生成一个流量概况文件。它会寻找统计上不寻常的分组流,例如 ICMP 分组不寻常的百分比或端口扫描指数性突然增长。基于异常的 IDS 最大的特点就是不依赖现有攻击的以前只是,另一方面区分正常流量和统计异常流量也是一个挑战。至今大多数部署的 IDS 主要是基于特征的。
进程和线程
进程
多道程序环境下允许多个程序并发执行,进程就是为了更好地描述和控制程序的并发执行,实现操作系统的并发性和共享性。
进程就是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。系统资源指的是处理机、存储器和其他设备服务于某个进程的时间,例如把处理机资源理解为处理机的时间片才是准确的。因为进程是这些资源分配和调度的独立单位,这就决定了进程一定是一个动态的、过程性的概念。
结构
①进程控制块PCB:进程实体的一部分,进程存在的唯一标识,包括进程描述信息、控制和管理信息、资源分配清单和处理机相关信息。
②程序段:就被进程调度程序调度到CPU执行的程序代码段。
③数据段:进程对应的程序加工处理的原始数据,也可以是程序执行时产生的中间或最终结果。
特征
①动态性 进程是一次程序的执行,具有一定的生命周期,是动态地产生、变化和消亡的。动态性是进程最基本的特征。
②并发性 指多个进程同时存在于内存中,能在一段时间内同时运行。并发性是进程的重要特征,也是操作系统的重要特征。进入进程的目的就是为了使程序能与其他进程的程序并发执行,提高资源利用率。
③独立性 指进程实体是一个能独立运行、独立获得自由和独立接受调度的基本单位。
④异步性 由于进程的相互制约,会使进程具有执行的间断性,即进程按各自独立的,不可预知的速度向前推进。
⑤结构性 每个进程都配置有一个进程控制块PCB对其进行描述,从结构上看进程实体是由程序段、数据段和PCB组成的。
进程的状态和转换
①运行态 进程正在处理机上运行
②就绪态 进程已处于准备运行的状态,获得了除处理机外的一切资源
③阻塞态 进程正在等待某一事件而暂停运行,如等待某资源可用或等待输入/输出流
④创建态 进程正在被创建,尚未转到就绪态
⑤结束态 进程正从系统中消失,可能是正常结束或其他原因中断退出
就绪->运行:处于就绪状态的进程被调度后,获得处理机资源(分派处理机时间片)
运行->就绪:处于运行态的进程在时间片用完后,不得不让出处理机。在可剥夺的操作系统中,当有更高优先级的进程就绪时,调度程序将正在执行的进程转为就绪态,让更高优先级的进程执行。
运行->阻塞:进程请求某一资源的使用和分配或等待某事件的发生(如IO完成),进程以系统调用的形式请求操作系统提供服务。
阻塞->就绪:进程等待的事件到来时,如IO结束或中断结束时,中断处理程序必须把相应进程的状态由阻塞转为就绪态。
进程控制
进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态转换等功能。
进程创建
允许一个进程创建另一个进程,创建者为父进程,被创建者为子进程。子进程可以继承父进程所拥有的资源,当子进程被撤销时,应将父进程的资源归还。撤销父进程时,必须同时撤销所有子进程。
①为新进程分配一个唯一的进程标识号,并申请一个空白PCB。②为进程分配资源,为新进程的程序和数据分配必要内存空间。若资源不足不会创建失败而是进入阻塞态。③初始化PCB,包括标志信息,处理机状态信息,进程优先级等。④若进程就绪队列未满,就将新进程插入就绪队列等待被调度。
进程终止
正常结束,表示进程任务已经完成并准备退出运行。异常结束,表示进程在运行时发生了某种异常,使程序无法继续运行,例如非法指令,IO故障等。外界干预,指进程因为外界请求而终止,例如操作系统干预或父进程请求终止等。
①根据被终止进程的标识符,检索PCB,读出该进程的状态。②若处于执行状态,终止执行,将处理机资源分配给其他进程。③若进程还有子进程,应将所有子进程终止。④将该进程的全部资源归还给父进程或操作系统。⑤将PCB从所在队列删除。
进程阻塞
①找到将要被阻塞进程的PCB。②如果为运行态,保护现场转为阻塞态,停止运行。③把PCB插入相应事件的等待队列。
进程唤醒
①在该事件的等待队列中找到进程对应的PCB。②将其从等待队列中移除,设置状态为就绪态。③将PCB插入就绪队列,等待调度程序调度。
进程切换
①保存处理机上下文,包括程序计数器和其他寄存器。②更新PCB信息。③把进程的PCB移入相应的队列。④选择另一个进程执行并更新其PCB。⑤更新内存管理的数据结构。⑥恢复处理机上下文。
进程通信
①共享存储:在通信的进程之间存在一块可以直接访问的共享空间,共享存储分为两种:低级的共享基于数据结构,高级的共享基于存储区。操作系统只负责为通信进程提供可共享的存储空间和同步互斥工具,数据交换由用户自己安排读写指令完成。
②消息传递:进程间的数据交换以格式化的消息为单位,进程提供系统提供的发送消息和接收消息两个原语进行数据交换。消息传递分为:直接通信方式,把消息挂在接收进程的消息缓存队列上。间接通信方式,发送进程把消息发送到某个中间实体,中间实体一般称作信箱,相应的通信系统为电子邮件系统。
③管道通信:消息传递的一种特殊方式,管道就是连接一个读进程和一个写进程来实现它们通信的一个共享文件。管道可以理解为共享存储的优化和发展,管道通信中存储空间优化为缓冲区,缓冲区只允许一边写入另一边读出,只要缓冲区有数据进程就能从缓冲区读出,只要有数据写进程就不会往缓冲区写数据,因此管道通信是半双工通信。
线程
引入进程的目的是为了多道程序更好的并发执行,提高资源利用率和吞吐量;引入线程的目的是为了减少程序在并发执行时的时空开销,提高操作系统的并发性能。
线程就是一种轻量级的进程,是一个基本的CPU执行单位,也是程序执行流的最小单元,由线程ID、程序计数器、寄存器集合和堆栈组成。线程是进程中的一个实体,是操作系统独立调度和分配的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它与同一进程下的其他线程共享进程的全部资源。
线程和进程的区别
①调度:进程是拥有资源的基本单位,而线程是独立调度的基本单位。在同一进程中,线程的切换不会引起进程的切换。在不同进程中线程的切换会引起进程切换。
②拥有资源:不管是传统操作系统还是有线程的操作系统,进程都是拥有资源的基本单位,而线程不拥有系统资源,只有一点运行中必不可少的资源。如果线程也是拥有资源的单位,那么切换线程就需要较大的时空开销,它的引入就没有意义。
③系统开销:创建和撤销进程涉及资源的分配和回收,操作系统的开销远大于创建或撤销线程的开销。进程切换也需要涉及CPU环境的保存和新调度到进程CPU环境的设置,但线程切换只需要保存和设置少量的寄存器容量,开销很小。
④地址空间:进程的地址空间之间互相独立,同一进程的各个线程共享进程的资源,进程内的线程对其他进程不可见。
⑤通信:进程间通信需要同步和互斥手段的辅助,保证数据一致性。线程可以直接读写进程数据段(全局变量)来进行通信。
线程的实现方式
①用户级线程:有关线程管理的所有工作都由应用程序完成,内核意识不到线程的存在。
②内核级线程:线程管理的所有工作都由内核完成,应用程序没有进行线程管理的代码,只有一个到内核级线程的编程接口。
死锁
死锁就是指多个进程因为互相竞争资源而陷入的一种僵局,如果没有外力的作用,这些进程都无法继续向前推进。
死锁的原因包含了:
①不可剥夺资源数量的不足,如果是可剥夺资源是不会造成死锁的。
②进程的推进顺序非法,进程请求和释放资源的顺序不当,例如进程P1和P2分别占用资源R1和R2,而此时P1和P2又分别申请资源R2和R1。
③信号量的使用不当,彼此等待对方的消息。
死锁有四个必要条件:
①互斥条件,进程对资源的占用具有排他性控制,如果进程请求的资源已被占用,请求就会被阻塞。
②不可剥夺条件,当一个资源没有被使用完成前是不能被其他进程强行获取的,只有占用它的进程主动释放才可以。
③请求和保持条件,一个进程已经占有了某个资源,又要请求其他资源,而该资源被其他进程占用,请求被阻塞,但进程也不会释放自己已经占有的资源。
④循环等待条件,存在一个进程资源的循环等待链,链中每个进程已经占有的资源同时是其他进程请求的资源。
预防
事先预防,实现起来比较简单,但是条件严格,效率很低。
①破坏互斥条件,系统中的所有资源都允许共享,但是有的资源不能同时访问,不太现实。
②破坏不可剥夺条件,允许剥夺其他进程已经占有的资源,可能会造成前段工作的失效,如果频繁发送就会增加系统开销,严重降低系统的吞吐量。
③破坏请求和保持条件,采用预先资源分配法,一次性分配进程需要的所有资源,缺点是会严重浪费系统资源。
④破坏循环等待条件,采用顺序资源分配法, 缺点是会造成编程不便。
避免
同样也是事先预防,不同的是动态地根据情况来避免死锁,性能比较好。
①系统安全状态,不安全的系统可能会导致死锁,安全的系统状态不会导致死锁,如果资源分配不会进入不安全的系统状态就给进程分配资源。
②银行家算法,把操作系统视为银行家,操作系统管理的资源视为资金,进程向操作系统申请资源相当于贷款。采用预先资源分配策略,主要的数据结构是可利用的资源向量,分配矩阵,需求矩阵,最大需求矩阵。
检测
画出资源分配图,圆圈表示进程,框表示一类资源。进程到资源是请求边,资源到进程是分配边。然后利用死锁定理来简化资源分配图,如果S不可被完全简化那么代表是一个死锁。
解除
如果没有采取死锁的预防和避免,就要采用死锁的检测和解除。
①资源剥夺法:挂起某些死锁进程并剥夺其资源。
②撤销进程法:撤销一个甚至全部死锁进程并剥夺其资源。
③进程回退法:让一个或多个进程回到不至于造成死锁的状态。
|