概述:

(1)应用层:两个应用程序之间(报文)
(2)运输层:两终端(如个人PC机)之间(报文段)
(3)网络层:端系统和路由之间(数据报)
(4)链路层:各节点(还多了链路层交换机)之间的路径上(帧)
(5)物理层:将帧的各比特在各节点之间传播(比特)

一、应用层

1、进程与计算机网络之间的接口

进程通过一个称为套接字的软件接口向网络发送报文和从网络接收报文。这里,进程可以类比于一个房子,而它的套接字相当于它的门,当一个进程想向位于另一台主机上的另一个进程发送报文时,就把报文推出该门(套接字)。一旦该报文抵达目的主机,它通过接受进程的门(套接字)传递,然后接收进程对该报文进行处理。
由于该套接字是建立网络应用程序的可编程接口,因此套接字也称为应用程序与网络之间的应用程序编程接口。

2、何为应用层协议

应用层协议定义了在运行在不同端系统上的应用程序如何相互传递报文,具体:
交换的报文类型,例如请求报文和响应报文。
各种报文类型的语法。
字段的语义,即字段中包含信息的含义。
一个进程何时以及如何发送报文,对报文响应的规则。

3、SSL

因为隐私和其它安全问题对许多应用而言已经成为至关重要的问题,所以安全套接字层(Secure Sockets Layer,SSL)应运而生。SSL提供了关键的进程到进程的安全性服务,包括加密,数据完整性和端点鉴别。需要强调的是,SSL不是与TCP和UDP在相同层次的运输协议,而是一种对TCP的加强,这种加强实在应用层实现的。

4、HTTP

HTTP定义了Web客户向Web服务器请求Web页面的方式,以及服务器向客户传送Web页面的方式。HTTP服务器并不保存关于客户的任何信息,所以我们说HTTP是一个无状态协议。
HTTP可以使用非持续连接或持续连接。非持续连接中每个TCP连接在服务器发送一个对象后关闭,即该连接不为其它的对象而持续下来,只传输一个请求报文和一个响应报文。而持续连接中,如果一条连接经过一定时间间隔仍未被使用,HTTP服务器才关闭该连接。HTTP的默认模式是使用带流水线的持续连接。

(1)HTTP请求报文格式

下面提供了一个典型的HTTP 请求报文:

GET /somedir/page.html HTTP/l.l 
Host: www.someschool.edu 
Connection: close 
User-agent: Mozilla/5.0 
Accept-language: fr 

HTTP 请求报文的第一行叫做请求行 (request line) ,其后继的行叫做首部行( header line)。请求行有个字段:方法字段、URL字段和HTTP 版本字段。你也许认为该首部行是不必要的,因为在该主机中已经有一条 TCP连接存在了,但是,该首部行提供的信息是 Web 代理高速缓存所要求的。通过包含Connection: close 首部行,该浏览器告诉服务器不希望麻烦地使用持续连接,它要求服务器在发送完被请求的对象后就关闭这条连接。User- agent: 首部行用来指明用户代理,即向服务器发送请求的浏览器的类型。
通用格式如下:
图片1.png
值得注意的是,这里的请求包体不需要编码为ASCII码。

(2)HTTP响应报文格式

下面我们提供了一条典型的 HTTP 响应报文:
HTTP/ 1. 1 200 OK
Connection: close 应用层
Date: Tue , 09 Aug 2011 15:44:04 GMT
Server: Apache/2.2.3 (CentOS)
Last-Modified: Tue , 09 Aug 2011 15:11:03 GMT
Content-Length: 6821
Content-Type: text/html
(data data data data data ...)
它有三个部分:初始状态行 (sLatus line) ,首部行 (header 1ine) ,实体体 (enLity body)。
通用格式如下:
图片2.png
一些常见的状态码和相关短语包括:
200 OK:表示客户端请求成功;
400 Bad Request:表示客户端请求有语法错误,不能被服务器所理解;
401 Unauthonzed:表示请求未经授权,该状态代码必须与 WWW-Authenticate 报头域一起使用;
403 Forbidden:表示服务器收到请求,但是拒绝提供服务,通常会在响应正文中给出不提供服务的原因;
404 Not Found:请求的资源不存在,例如,输入了错误的URL;
500 Internal Server Error:表示服务器发生不可预期的错误,导致无法完成客户端的请求;
503 Service Unavailable:表示服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常;

(3)cookie

 HTTP协议作为无状态协议,对于HTTP协议而言,无状态同样指每次request请求之前是相互独立的,当前请求并不会记录它的上一次请求信息。那么问题来了,既然无状态,那完成一套完整的业务逻辑,发送多次请求的情况数不胜数,使用http如何将上下文请求进行关联呢?机智的人类通过优化,找到了一种简单的方式记录http协议的请求信息。
浏览器发送request请求到服务器,服务器除了返回请求的response之外,还给请求分配一个唯一标识ID,协同response一并返回给浏览器。
同时服务器在本地创建一个MAP结构,专门以key-value(请求ID-会话内容)形式将每个request进行存储。
此时浏览器的request已经被赋予了一个ID,第二次访问时,服务器先从request中查找该ID,根据ID查找维护会话的content内容,该内容中记录了上一次request的信息状态。
根据查找出的request信息生成基于这些信息的response内容,再次返回给浏览器。如果有需要会再次更新会话内容,为下一次请求提供准备。
所以当我们有cookie时,往往能在一个网站直接显示登录账号和登录密码,这两个信息是存在服务器的而不是本机的(以前一直都有的疑惑),通过cookie生成的响应报文包含了账号密码信息。以前还有一个疑惑,就是当本地删除了cookie文件后,下次访问该网站又会生产新的cookie,那难道服务器的账号密码信息一直存着不就占位子吗,实际上,服务器上的cookie信息都是有过期时间的,这在报文中其实也会有记录(expire time)的并存在cookie文件中。
一般cookie所具有的属性,包括:
Domain:域,表示当前cookie所属于哪个域或子域下面。
对于服务器返回的Set-Cookie中,如果没有指定Domain的值,那么其Domain的值是默认为当前所提交的http的请求所对应的主域名的。比如访问 http://www.example.com,返回一个cookie,没有指名domain值,那么其为值为默认的www.example.com。
Path:表示cookie的所属路径。
Expire time/Max-age:表示了cookie的有效期。expire的值,是一个时间,过了这个时间,该cookie就失效了。或者是用max-age指定当前cookie是在多长时间之后而失效。如果服务器返回的一个cookie,没有指定其expire time,那么表明此cookie有效期只是当前的session,即是session cookie,当前session会话结束后,就过期了。对应的,当关闭(浏览器中)该页面的时候,此cookie就应该被浏览器所删除了。
secure:表示该cookie只能用https传输。一般用于包含认证信息的cookie,要求传输此cookie的时候,必须用https传输。
httponly:表示此cookie必须用于http或https传输。这意味着,浏览器脚本,比如javascript中,是不允许访问操作此cookie的。

(4)web缓存

Web缓存器也叫代理服务器,它能够缓存最近请求过的对象的副本,若Web缓存器中有请求的资源,则立刻返回之,而不需要再向目标服务器请求该资源。
但是如何确保缓存服务器中自身副本是最新的呢?使用的是条件GET方法:
如果请求报文使用GET方法,且包含一个”If-Modified-Since”首部行,那么这个报文就是一个条件GET请求报文。
每次有新的请求,Web服务器就会发送一个条件GET请求报文(上次缓存该资源会记录该资源最后修改的时间),来判断该资源从自己缓存后是否有修改过,这样就确保了自身副本的有效性。

5、FTP

HTTP FTP 都是文件传输协议,并且有很多共同的特点,例如,它们都运行在 TCP,然而,这两个应用层协议也有一些重要的区别 其中最显著的就是 FTP 使用了两个并行的 TCP 连接来传输文件, 个是控制连接 (control connection) ,一个是数据连接( data connection) 控制连接用于在两主机之间传输控制信息,如用户标识、口令、改变远程目录的命令以及"存放”(put)” 和”获取(get) “文件的命令。数据连接用于实际发送一个文件。而对FTP传输而言,控制连接贯穿了整个用户会话期间,但是对会话巾的每一次文件传输都需要建立一个新的数据连接(即数据连接是非持续的)。FTP 服务器必须在整个会话期间保留用户的状态( state) 。
一些较为常见的命令如下:
• USER usemame: 用于向服务器传送用户标识
• PASS password: 用于向服务器发送用户口令
• LIST: 用于请求服务器回送当前远程目录中的所有文件列表 该文件列表是经一个(新建且非持续连接)数据连接传送的,而不是在控制 TCP 连接上传送。
• RETR filename: 用于从远程主机当前目录检索(即get) 文件 该命令引起远程主机发起一个数据连接,并经该数据连接发送所请求的文件。
• STOR filename: 用于在远程主机的当前目录上存放(即 put) 文件 。
一些典型的回答连同它们可能的报文如下所示:
• 331 Usemame OK , Password required (用户名 OK ,需要口令)
• 125 Data connection already open; transfer starting (数据连接已经打开,开始传送)
• 425 Can' L open data connection (无法打开数据连接)
• 452 Error writing file (写文件差错)

6、电子邮件

电子邮件系统有三个主要的组成部分:
用户代理,邮件服务器和简单邮件传输协议(Simple Mail Transfer Protocol,SMTP)。其中用户代理允许用户阅读、回复、转发、保存和撰写报文。
图片3.png
图片4.png

(1)STMP

STMP使用TCP可靠数据传输服务,用的是持续连接:如果发送邮件服务器有几个报文同时发往同一个接受邮件服务器,它可以通过同一个TCP连接发送这些报文。

一个典型的报文首部如下:
From: alice@crepes.fr
To: bob@hamburger.edu
Subject: Searching for the meaning of life.
每个首部必须含有一个From:首部行和一个To:首部行;一个首部也许包含一个Subject:首部行以及其它可选的首部行。在报文首部之后,紧接着是一个空白行,然后是以ASCII格式表示的报文主体。

多用途因特网邮件扩展(MIME)是对RFC 822的扩展。
支持多媒体的两个关键MIME首部是Content-Type:和Content-Transfer-Encoding:。
图片5.png

简单比较一下STMP和HTTP,他们都是传送文件的协议,并且持续的HTTP和SMTP都使用的是持续连接。但是他们也有一些区别:
A、HTTP主要是一个拉协议,用户使用HTTP从服务器拉去一些信息,特别是TCP连接是由想接受文件的机器发起的。而STMP基本是一个推协议,TCP连接是由要发送该文件的机器发起的。
B、STMP要求每个报文使用7比特的ASCII码格式,HTTP不受这种限制。
C、HTTP将每个对象封装到自己的HTTP响应报文中,而SMTP则把所有报文对象放在一个报文之中。

(2)邮件访问协议

在Alice向Bob发送邮件的过程中,Bob是如何通过运行在他本地PC上的用户代理,获得位于某ISP的邮件服务器上的他的邮件呢?注意到Bob的用户代理不能使用SMTP来取回邮件,因为取邮件时一个拉操作,而SMTP是一个推协议。因此我们要引入邮件访问协议。
邮件访问协议有:
·POP3:第三版邮局协议 [RFC 1939]
·IMAP:互联网邮件访问协议 [RFC 1730]
·HTTP:Hotmail , Yahoo! Mail等
  POP3是Post Office Protocol 3的简称,即邮局协议的第3个版本,是TCP/IP协议族中的一员(默认端口是110)。本协议主要用于支持使用客户端远程管理在服务器上的电子邮件。POP3协议允许电子邮件客户端下载服务器上的邮件,但是在客户端的操作(如移动邮件、标记已读等),不会反馈到服务器上,比如通过客户端收取了邮箱中的3封邮件并移动到其他文件夹,邮箱服务器上的这些邮件是没有同时被移动的 。
IMAP全称是Internet Mail Access Protocol,即互联网邮件访问协议,是一个应用层协议(端口是143)。IMAP服务器把每一个把每个报文与一个文件夹联系起来;当报文第一次到达服务器时,它与收件人的INBOX文件夹相关联。收件人则能够把邮件移动到一个新的、用户创建的文件夹中,阅读和删除邮件。IMAP另一个重要特性是它具有允许用户代理获取报文组件的命令,比如比读取一个报文的首部或多部份MIME报文的一部分。
IMAP和POP3的区别:
(1)IMAP提供Webmail与电子邮件客户端之间的双向通信,客户端收取的邮件仍然保留在服务器上,同时在客户端上的操作都会反馈到服务器上。而POP3在客户端的操作不会反馈到服务器上。
(2)IMAP提供的摘要浏览功能可以让你在阅读完所有的邮件到达时间、主题、发件人、大小等信息后才作出是否下载的决定。
(3)POP3需要下载未阅读的邮件,IMAP可以不用把所有的邮件全部下载,而是通过客户端直接对服务器上的邮件进行操作。所有通过IMAP传输的数据都会被加密,从而保证通信的安全性。

7、DNS

能进行主机名到地址转换的目录服务,就是域名系统(Domain Name System , DNS) 的主要任务。DNS 是:
1.一个由分层的 DNS 服务器( DNS server) 实现的分布式数据库;
2.一个使得主机能够查询分布式数据库的应用层协议;
DNS 服务器通常是运行 BIND (Berkeley Internet Name Domain) 软件[ BIND 2012 UNJX 机器。DNS协议运行在UDP之上,使用 53 号端口。
为了使用户的主机能够将一个 HTTP请求报文发送到Web服务器 www someschool. edu,该用户主机必须获得www. someschool. edu的IP地址,其做法如下:
1.同一台用户主机上运行着 DNS 应用的客户端。
2.浏览器从上述 URL中抽取出主机名 www. someschool. edu ,并将这台主机名传给DNS 应用的客户端。
3.DNS 客户向 DNS 服务器发送一个包含主机名的请求。这里客户首先与根服务器之一联系,它将返回顶级域名edu的TLD(Top-Level Domain,顶级域)服务器的IP地址。该客户则与这些TLD服务器之一联系,它将为 someschool. edu返回权威服务器的 IP 地址。最后,该客户与someschool. edu权威服务器之一联系,它为主机名www. someschool. edu返回其IP地址。
4.DNS 客户最终会收到一份回答报文,其中含有对应于该主机名的 IP 地址。
5.一旦浏览器接收到来自 DNS 的该IP地址,它能够向位于该 lP 地址80端口的HTTP服务器进程发起一个 TCP 连接。

除了主机名到IP地址的转换外,DNS还提供一些重要的服务:
1.主机别名。有着复杂主机名的主机能拥有一个或多个别名。应用程序可以调用DNS来获得主机别名对应的规范主机名以及主机的IP地址。
2.邮件服务器别名。
3.负载分配。一个IP地址集合可以与同一个规范主机名相联系。DNS数据库中存储着这些IP地址的集合。当客户对映射到某地址集合的名字发出一个DNS请求时,该服务器用IP地址的整个集合进行响应,但在每个回答中循环这些地址的次序。所以就循环分配了负载。 这里DNS服务器的分配算法采用的最简单的轮询算法。
使用DNS进行负载分配的缺点:
1.目前的DNS是多级解析的,每一级DNS都可能缓存A记录,当某台服务器下线之后,即使修改了A记录,要使其生效也需要较长的时间,这段时间,DNS任然会将域名解析到已下线的服务器上,最终导致用户访问失败。
2.不能够按服务器的处理能力来分配负载。DNS负载均衡采用的是简单的轮询算法,不能区分服务器之间的差异,不能反映服务器当前运行状态,所以其的负载均衡效果并不是太好。
3.可能会造成额外的网络问题。为了使本DNS服务器和其他DNS服务器及时交互,保证DNS数据及时更新,使地址能随机分配,一般都要将DNS的刷新时间设置的较小,但太小将会使DNS流量大增造成额外的网络问题。

DNS系统还有一个非常重要的特色:DNS缓存。DNS缓存的原理非常简单。在一个请求链中,当某DNS服务器接收一个DNS回答时,它能将该回答中的信息缓存在本地存储器中,一段时间后(通常设置为两天)再丢弃缓存的信息。
每个DNS回答报文包含了一条或多条资源记录。资源记录是一个包含了下列字段的4元组:
(Name,Value,Type,TTL)
TTL是该记录的生存时间,它决定了资源记录应当从缓存中删除的时间。Name和Value的值取决于Type:
如果Type=A,则Name是主机名,Value是该主机名对应的IP地址。
如果Type=NS,则Name是个域(如foo.com),而Value是个知道如何获得该域中主机IP地址的权威DNS服务器的主机名。
如果Type=CNAME,则Value是别名为Name的主机对应的规范主机名。
如果Type=MX,则Value是个别名为Name的邮件服务器的规范主机名。

8、BitTorrent

先来一个总结:该协议简单来说就是客户分担了服务器的上载。
参与一个特定文件分发的所有对等方的集合被称为一个洪流。在一个洪流中的对等方彼此下载等长度的文件块,典型的块长度为256KB。当一个对等方加入某洪流时,它向追踪器注册自己,并周期性地通知追踪器它仍在该洪流中。
在该洪流中的Alice周期性地(经TCP连接)询问每个邻近对等方它们所具有的块列表。因此在任何给定的时刻,Alice将具有块的子集并知道它的邻居具有哪些块。这里就会有几个问题:
第一,她应当从她的邻居请求那些块呢?
这里使用的是一种称为最稀缺优先的技术:针对她没有的块在她的邻居中决定最稀缺的块(最稀缺的块就是那些在她的邻居中副本数量最少的块),并首先请求那些最稀缺的块。这样,最稀缺块得到更为迅速的重新分发,其目标是均衡每个块在洪流中的副本数量。
第二,她应当向哪些向她请求块的邻居发送?
这里使用了一种对换算法:对于当前能够以最高速率向她提供数据的邻居,给出其优先权。

二、运输层

1、多路复用与多路分解

将主机间交付扩展到进程间交付被称为运输层的多路复用与多路分解:
一个进程有一个或多个套接字,它相当于从网络向进程传递数据和从进程向网络传递数据的门户。因此,在接收主机中的运输层实际上并没有直接将数据交付给进程,而是将数据交给了一个中间的套接字。
每个运输层报文段中具有几个字段,在接收端,运输层检查这些字段,标识出接收套接字,进而将报文段定向到该套接字。将运输层报文段中的数据交付到正确的套接字的工作称为多路分解。在源主机从不同套接字中收集数据块,并为每个数据块封装上首部信息(这将在以后用于分解)从而生成报文段,然后将报文段传递到网络层,所有这些工作称为多路复用。
(1)无连接的多路复用与多路分解
一个UDP套接字是由一个二元组来全面标识的,该二元组包含一个目的IP地址和一个目的端口号。因此,如果两个UDP报文段有不同的源IP地址和/或源端口号,但具有相同的目的IP地址和目的端口号,那么这两个报文段将通过相同的目的套接字被定向到相同的目的进程。
(2)面向连接的多路复用与多路分解
TCP套接字是由一个四元组(源IP地址,源端口号,目的IP地址,目的端口号)来标识的。特别与UDP不同的是,两个具有不同源IP地址或源端口号到达TCP报文段将被定向到两个不同的套接字,除非TCP报文段携带了初始创建链接的请求。

这里有一个思考:UDP的socket是二元组而TCP的是四元组的本质原因就是UDP是无连接的,发就完事了,而TCP是面向连接的,不可能同时几台主机与同一个socket建立连接。

2、UDP

UDP只是做了运输协议能够做的最少工作。除了复用/分解功能及少量的差错检测外,它几乎没有对IP增加别的东西。许多应用更适合UDP的原因主要有以下几点:
关于何时、发送什么数据的应用层控制更为精细。采用UDP时,只要应用进程将数据传递给UDP,UDP就会将此数据打包进UDP报文段并立即将其传递给网络。实时应用通常不希望过分地延迟报文段的发送,并且能容忍一些数据的丢失,TCP服务模型不是特别适合这些应用。
1.无需连接建立。UDP不需要任何准备即可进行数据传输。因此UDP不会引入建立连接的时延。
2.无连接状态。连接状态包括接收和发送缓存、拥塞控制参数以及需要和确认号的参数。要实现TCP的可靠数据传输服务并提供拥塞控制,这些状态信息是必要的。UDP不维护连接状态,即不跟踪这些参数,因此,某些服务器当应用程序运行在UDP之上而不是TCP之上时,一般都能支持更多的活跃客户。
分组首部开销小。TCP首部开销20字节,UDP开销8字节。
其实使用UDP的应用是可以实现可靠数据传输的,只是这需要在应用程序自身中建立可靠性机制来完成,即把运输层的工作放在了应用层进行。

UDP的报文段结构如下:
图片6.png
长度:字段指示了在UDP报文段中的字节数(首部加数据)。
检验和:发送方的UDP对报文段中的所有16比特字的和进行反码运算,求和时遇到的任何溢出都被回卷。得到的结果就被放在UDP报文段中的检验和字段中。在接收方,全部的16比特字(包括检验和)加在一起。如果该分组中没有引入差错,则在接收方处该和将是1111111111111111。

3、TCP

TCP是面向连接的,一旦建立起一条TCP连接,两个应用进程之间就可以相互发送数据了。TCP将这些数据引导到该连接的发送缓存(发送缓存是在三次握手初期设置的缓存之一)中,接下来TCP就会不时从发送缓存中取出一块数据。TCP规范中描述“TCP应该在它方便的时候以报文段的形式发送数据”。TCP可从缓存中取出并放入报文段中的数据数量受限于最大报文段长度(Maximum Segment Size,MSS)。MSS通常根据最初确定的由本地发送的最大链路层帧长度(即所谓的最大传输单元(Maximum Transmission Unit,MTU))来设置。以太网和PPP链路层协议都具有1500字节的MTU,因此MSS的典型值为1460字节。

TCP报文段结构如下:
图片7.png
其中检验和与UDP一样,6比特的标志字段意义中,ACK比特用于指示确认字段中的值是有效的。RST、SYN、和FIN比特用于连接建立和拆除。PSH比特指示接收方应立即将数据交给上层。URG比特用于指示报文段中存在着被发送端的上层设置为“紧急”的数据。紧急数据的最后一个字节由16比特的紧急数据指针字段指出。(实践中,PSH、URG和紧急数据指针并没有使用)。

(1)序号与确认号
一个报文段的序号是该报文段首字节的字节流编号,假定数据流由一个包含500000字节的文件组成,其MSS为1000字节,数据流的首字节编号是0,该TCP将为该数据流构建500各报文段。给第一个报文段分配序号0,第二个报文段分配序号1000,第三个报文段分配序号2000,以此类推。
而确认号是当前主机期望从通信主机收到的下一字节的序号。
再举一个例子,假设主机A已收到一个来自主机B的包含字节0 ~ 535的报文段,以及另一个包含字节900 ~ 1000的报文段。由于某种原因,主机A还没有收到字节536 ~ 899的报文段。在这个例子中,主机A仍在等待字节536,因此,A到B的下一个报文段将在确认号字段中包含536。因此,TCP被称为提供累计确认。

(2)往返时间的估计与超时
在如TCP这样的实际协议中实现超时/重传机制时还是会产生许多微妙的问题的。其中最明显的一个问题就是超时间隔长度的设置。显然,超时间隔必须大于该连接的往返时间(RTT),即从一个报文段发出到它被确认的时间。
报文段的样本RTT(表示为SampleRTT)就是从某报文段被发出(即交给IP)到该报文段的确认被收到之间的时间量。大多数TCP的实现仅在某个时刻做一次SampleRTT测量,TCP维持一个SampleRTT均值(称为EstimatedRTT)。一旦获得一个新的SampleRTT时,TCP就会根据公式更新EstimatedRTT。除了估算RTT外,测量RTT的变化也是有价值的。RTT偏差DevRTT用于估算SampleRTT一般会偏离EstimatedRTT的程度。
显而易见,超时间隔应该等于EstimatedRTT加一个余量,所以当SampleRTT值波动较大时,余量应该大些,波动较小时,余量应该小些,这时DevRTT就发挥作用了,一般TimeoutInterval = EstimatedRTT + 4 * DevRTT。
TCP中,每当超时时间发生时,TCP重传具有最小序号的还未被确认的报文段。只是每次TCP重传时都会将下一次的超时间隔设为先前值的两倍,而不是用从EstimatedRTT和DevRTT推算出的值。然而,每当定时器在另两个时间(即受到上层应用的数据和收到ACK)中的任意一个启动时,TimeoutInterval由最近的EstimatedRTT值与DevRTT值推算得到。

(3)快速重传
一旦收到3个冗余ACK(总共收到4个),TCP就执行快速重传,即在该报文段的定时器过期之前重传丢失的报文段。
那么,TCP确认是累积式的,它是否是一个GBN(回退N步,重新从超时的报文段开始发送)协议呢,答案是否定的,许多TCP实现会将正确接收但失序的报文段缓存起来。

(4)流量控制
TCP为它的应用程序提供了流量控制服务,以消除发送方使接收方缓存溢出的可能性。
TCP通过让发送方维护一个称为接收窗口(报文段中的窗口)的变量来提供流量控制。接收窗口用rwnd表示,根据接收方缓存可用空间的数量来设置:
rwnd = RcvBuffer - (LastByteRcvd - LastByteRead)
发送方则跟踪LastByteSent - LastByteAcked的值,即发送方发送到连接中但未被确认的数据量。通过将未确认的数据量控制在值rwnd以内,就可以保证接收方的接收缓存不会溢出。
特殊地,当接收主机的接收窗口为0时,发送主机继续发送只有一个字节数据的报文段。这些报文段将会被接收方确认,最终缓存开始清空,并且确认报文中将包含一个非0的rwnd值。

(5)TCP的连接与关闭
建立一条TCP连接流程如下:
1.客户端的TCP向服务器端的TCP发送一个特殊的TCP报文段。该报文段中不包含应用层数据。但是在报文段的首部中的SYN标志位被置为1。另外,客户回随机地选择一个初始序号(client_isn)放在序号字段中。
2.服务器为该TCP连接分配TCP缓存和变量,并向该客户TCP发送允许连接的报文段,这个报文段也不包含应用层数据,但是SYN被置为1,确认号字段被置为client_isn + 1,并选择一个初始序号。
3.客户也为该连接分配缓存和变量,然后向服务器再发送一个报文段,该报文段可以在报文段负载中携带客户到服务器的数据。
图片8.png

为什么不使用两次握手呢?
因为若服务器发送的SYNACK报文段没有成功发送到客户机,对服务器来说,一个连接已建立起来,会一直等客户机发消息,而对客户机来说,并没有建立这个连接,此时服务器资源就被浪费。

关闭一条TCP连接流程如下:
a.客户机发送一个FIN标志位被置为1的报文段。
b.服务器回送一个确认报文段。
c.服务器发送它自己的终止报文段,FIN标志位被置为1。
d.客户对这个服务器的终止报文段进行确认。
图片9.png

(6)SYN洪泛攻击
攻击者发送大量的SYN报文段,而不完成第三次握手的步骤。随着这种SYN报文段纷至沓来,服务器不断为这些半开连接分配资源,导致服务器的连接资源被消耗殆尽。现在有一种有效的防御系统,称为SYN cookie。
当服务器收到一个SYN报文段时,服务器不会为该报文段生成一个半开连接。相反,服务器生成一个初始TCP序列号,该序列号是SYN报文段的源和目的IP地址与端口号通过仅有服务器知道的哈希函数算得。重要的是,服务器并不记忆该cookie或任何对应与SYN的其它状态信息。(之前三次握手讲的方法分配了缓存和变量,即记录了状态信息)
如果客户是合法的,那么它将返回一个ACK报文段,当服务器收到ACK,需要验证该ACK是否与前面发送的某些SYN相对应(之前三次握手讲的方法分配了缓存和变量所以不需要验证)。做法是将SYNACK报文段中的源和目的地IP地址与端口号执行同样的哈希函数,如果结果+1与SYNACK报文段中的确认号相同的话,则认为该ACK对应于较早的SYN报文段,因此它是合法的,生成一个具有套接字的全开的连接。

(7)TCP拥塞控制
TCP必须使用端到端拥塞控制而不是网络辅助的拥塞控制。运行在发送方的TCP拥塞控制机制跟踪一个额外的变量,即拥塞窗口,使用cwnd表示。在一个发送方中未被确认的数据量不会超过cwnd和rwnd中的最小值,即LastByteSent - LastByteAcked <= min{cwnd,rwnd}。
那么,为什么拥塞窗口可以表示发送速率呢,因为在每个RRT的起始点,上面的限制条件允许发送方向该连接发送cwnd个字节的数据,在RRT结束时发送方接收对数据的确认报文,因此发送速率大概是cwnd/RTT字节/秒。
那么,一个TCP连接怎么感知路径上是否拥塞呢?一个丢包事件(超时或收到3个冗余ACK)意味着拥塞,一个确认报文段意味着通畅。

TCP拥塞控制算法包括慢启动,拥塞避免和快速恢复(注意别和快速重传搞混了)。
1.慢启动
当一条TCP连接开始时,cwnd值通常初始值为一个MSS。然后每收到一个确认报文将cwnd增加一个MSS,这一过程每过一个RTT发送速率就翻倍,呈指数增长。
何时终止慢启动呢?
a.超时:慢启动阈值ssthresh设置为cwnd/2,cwnd设为1,重新开始慢启动。
b.cwnd等于ssthresh时:转移到拥塞避免模式。
c.检测到3个冗余ACK:执行快速重传,进入快速恢复状态。

2.拥塞避免
每个RTT只将cwnd增加一个MSS。
何时终止拥塞避免呢?
a.超时:慢启动阈值ssthresh设置为cwnd/2,cwnd设为1,重新开始慢启动。
b.检测到3个冗余ACK:慢启动阈值ssthresh设置为cwnd/2,cwnd值减半(算上收到的3个冗余ACK,所以加上3个MSS),执行快速重传,进入快速恢复状态。

3.快速恢复
对于引起TCP进入快速恢复状态的缺失报文段,对每个冗余ACK,cwnd的值增加一个MSS。
何时终止快速恢复呢?
a.丢失报文段的一个ACK到达时:cwnd=ssthresh,进入拥塞避免状态。
b.超时:慢启动阈值ssthresh设置为cwnd/2,cwnd设为1,重新开始慢启动。

三、网络层

英特网的网络层有三个主要组件。第一个是IP协议,第二个是路由选择部分,它决定数据报从源到目的地所流经的路径。最后一个是报告数据报中差错和对某些网络层信息请求进行响应的设施,即英特网控制报文协议(ICMP)。

1、IP

(1)Ipv4数据报格式:

20191108185708268.png

版本:
这个4位字段定义了IP协议的版本,目前主流的版本是4。

首部长度:
这个4位字段定义了数据报首部的长度,以4字节的字为单位。当首部没有选项时,首部长度位20字节;当这个字段值位最大值F时,首部长度最大为60字节。

服务类型:
使不同类型的IP数据报能相互区别开来,如低延时,高吞吐量等等。

总长度:
这个16位字段定义了数据报总长度,其以字节为单位。故IPv4数据报总长度上限值位65536字节。

标识(identification):
这个16位字段标志了从源主机发出的一个数据报,这样就确定了数据报的唯一性。这样使得数据报被分片(数据报比链路层帧大的时候就会执行分片)后,在到达终点时终点能根据标识号将同一个数据报的分片重新组装成一个数据报。

标志(flag):
最后一个片为0,其余为1。这可以让目的主机确信它已收到了最后一个片

分片偏移:
这个13位字段表示的是分片在整个数据报中的相对位置。这是数据在原始数据报中的偏移量,以8字节位单位。
注:分片本身还可能进行分片,这种情况下,分片偏移值永远是相对于原始数据报的。

生存时间:
这个8位字段用来控制数据报所经过的最大跳数(路由器),每经过一个路由器,这个字段数值都减1,减1后变位0时,路由器就丢弃这个数据报。

协议:
这个8位字段定义了使用IPv4服务的高层协议,如TCP,UDP,ICMP,IGMP,OSPF等的数据都将被封装到IP数据报中。这个字段指明数据报必须交付给哪个最终目的协议。

检验和:
检验IP数据报首部。

(2)DHCP

因特网的地址分配策略被称为无类别域间路由选择(Classless Interdomain Routing,CIDR)。如一个子网地址为223.1.1.0/24,其中/24记法称为子网掩码。子网最主要的作用即是隔离。

那么如何获得一个IP呢?通常使用的是动态主机配置协议(Dynamic Host Configuration,DHCP),它允许主机自动获取一个IP地址。大致的方法就是当主机加入时,DHCP服务器从其当前可用的地址池中分配一个任意的地址给它;当一台主机离开时,其地址被收回这个池中。具体步骤如下:
1.DHCP服务器发现。新主机广播发送一个DHCP发送报文。
2.DHCP服务提供。DHCP服务器广播发送一个DHCP提供报文,包含发现报文的事务。
3. ID,向客户推荐的IP地址,网络掩码以及IP地址租用期。
4.DHCP请求。新主机向选中的服务器提供用一个DHCP请求报文响应。
5.DHCP ACK。服务器用DHCP ACK报文响应。

(3)网络地址转换NAT(Network Address Translation)

NAT路由器对外界的行为就如同一个具有单一IP地址的单一设备,所有离开家庭路由器和进入家庭的报文都有一个IP地址。那么,如果从广域网到NAT路由器的所有数据报都有相同的目的IP地址,那么该路由器如何知道它应该将某个分组转发给哪个内部主机呢?使用一张NAT转换表,即将LAN端IP和端口号映射为一个WAN端的一个端口号。
但是NAT存在一个问题,就是NAT转换表只能记录从内网向外网发送数据报的IP和端口号,这就导致只能由内向外请求连接,而无法从外部向内请求连接,故妨碍了P2P程序。目前许多P2P程序利用连接反转来实现NAT穿越,就是有一个服务器A,对等方B,C,D,其中A和B,C,D都连接,而B,C进行P2P连接,这时D可以通过A建立与B的一条TCP连接。
目前还有一种UPnP协议越来越多地用于NAT穿越,使用UPnP,在主机上运行的应用程序能够为某些请求的公共端口号请求一个NAT映射,该映射位于其(专用IP地址:专用端口号)和(公共IP地址:公共端口号)之间。

2、因特网控制报文协议(ICMP)

ICMP被主机和路由器用来彼此沟通网络层的信息。ICMP报文有一个类型字段和一个编码字段。众所周知的ping程序就是发送一个ICMP类型8编码0的报文到指定主机。

3、路由选择算法

使用的Dijkstra算法,步骤如下:
1.当前结点到相邻结点的费用 + 到当前节点的费用
2.比较最小路径表中到这些结点的费用与新算出来的费用,若更小,更新之
3.找表中费用最小的且不在结点子集中的结点,加入结点子集,并更新为当前结点。
4.找完了则结束,没找完就循环①。
5.在所有迭代中需要搜寻的结点总数为n(n + 1)/2,复杂度为O(N^2)。

(2)距离向量(Distance-Vector,DV)算法

每个结点x维护下列路由选择信息:
1.对于每个邻居v,从x到直接相连邻居v的费用c(x,v)
2.结点x的距离向量,包含x到N中所有目的地y的费用估计值
3.它的每个邻居的距离向量
在该算法中,每个结点不时地向它的每个邻居发送它的距离向量副本。当结点x从它的任何一个邻居v接收到一个新距离向量,它保存v的距离向量,然后使用Bellman-Ford方程更新它自己的距离向量:
D_x(y)=min_v{c(x,v) + D_v(y)}
对N中的每个结点v。其中D_x(y)指x到y的费用。
这种算法存在一个问题,即当某个链路的费用变得很大时,表单会循环更新很多很多次。解决办法就是增加毒性逆转:如果z通过y路由选择到目的地x,则z将通告y,它(z)到x的距离时无穷大的。

(3)因特网中的路由选择

整个网络的路由太多,路由选择算法很难收敛,故引入了自治系统(Autonomous System,AS)和自治系统内部路由选择协议。
自治系统内部的路由选择:RIP(路由选择信息协议,Routing Information Protocol)
RIP是一种距离向量算法,使用跳数作为其费用测度,即每条链路费用为1,一条路径的最大费用限制为15,邻居每30s交换一次信息,180s没有交换即认为该邻居不可达。
自治系统内部的路由选择:OSPF(开放最短路优先,Open Shortest Path First)OSPF核心就是一个使用洪泛链路状态信息的链路状态协议和一个Dijkstra最低费用路径算法。
自治系统间的路由选择:BGP(边界网关协议,Broder Gateway Protocol)
主要工作:
1.从相邻AS处获得子网可达性信息
2.向本AS内部的所有路由器传播这些可达性信息
3.基于可达性信息和AS策略,决定到达子网的好路由

(4)广播和多播路由

网络层提供以下两种服务:
1.广播路由选择:从一个源结点到网络中的所有其他结点交付分组。
2.多播路由选择:从单个源结点向其他网络结点的一个子集发送分组的副本。