0%

HTTP

1xx消息

这一类型的状态码,代表请求已被接受,需要继续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束。由于HTTP/1.0协议中没有定义任何1xx状态码,所以除非在某些试验条件下,服务器禁止向此类客户端发送1xx响应。 这些状态码代表的响应都是信息性的,标示客户应该采取的其他行动。

  • 100 - 客户端应当继续发送请求
  • 101 - 切换协议
  • 102 - 处理将被继续执行

2xx成功

这一类型的状态码,代表请求已成功被服务器接收、理解、并接受。

  • 200 - (成功)请求已成功,请求所希望的响应头或数据体将随此响应返回。
  • 201 - (已创建)请求成功且服务器已创建了新的资源。。
  • 202 - (已接受)服务器已接受了请求,但尚未对其进行处理。
  • 203 - (非授权信息)服务器已成功处理了请求,但返回了可能来自另一来源的信息。
  • 204 - (无内容)服务器成功处理了请求,但未返回任何内容。
  • 205 - (重置内容)服务器成功处理了请求,但未返回任何内容。
  • 206 - (部分内容)服务器成功处理了部分 GET 请求。

3xx重定向

这类状态码代表需要客户端采取进一步的操作才能完成请求。通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的Location域中指明。按照HTTP/1.0版规范的建议,浏览器不应自动访问超过5次的重定向。对重定向一般是由浏览器来控制重定向的次数,重定向会导致客户端不必要的资源消耗

  • 300 - 多重选择,被请求的资源有一系列可供选择的回馈信息。
  • 301 - 永久移除,被请求的资源已永久移动到新位置。
  • 302 - 临时移动,请求的资源现在临时从不同的URI响应请求。
  • 303 - 查看其他位置,对应当前请求的响应可以在另一个URI上被找到,而且客户端应当采用GET的方式访问那个资源。
  • 304 - 未修改。自从上次请求后,请求的网页未被修改过。服务器返回此响应时,不会返回网页内容。
  • 305 - 使用代理,被请求的资源必须通过指定的代理才能被访问。
  • 306 - 临时重定向,在最新版的规范中,306状态码已经不再被使用。
  • 307 - 临时重定向。

4xx客户端错误

这类的状态码代表了客户端看起来可能发生了错误,妨碍了服务器的处理。

  • 400 - 错误的请求。
  • 401 - 访问被拒绝。
  • 402 - 付款要求。
  • 403 - 禁止访问
    • 403.1 - 执行访问被禁止。
    • 403.2 - 读访问被禁止。
    • 403.3 - 写访问被禁止。
    • 403.4 - 要求 SSL。
    • 403.5 - 要求 SSL 128。
    • 403.6 - IP 地址被拒绝。
    • 403.7 - 要求客户端证书。
    • 403.8 - 站点访问被拒绝。
    • 403.9 - 用户数过多。
    • 403.10 - 配置无效。
    • 403.11 - 密码更改。
    • 403.12 - 拒绝访问映射表。
    • 403.13 - 客户端证书被吊销。
    • 403.14 - 拒绝目录列表。
    • 403.15 - 超出客户端访问许可。
    • 403.16 - 客户端证书不受信任或无效。
    • 403.17 - 客户端证书已过期或尚未生效。
    • 403.18 - 在当前的应用程序池中不能执行所请求的 URL。
    • 403.19 - 不能为这个应用程序池中的客户端执行 CGI。
    • 403.20 - Passport 登录失败。
  • 404 - 未找到。
    • 404.0 -(无) – 没有找到文件或目录。
    • 404.1 - 无法在所请求的端口上访问 Web 站点。
    • 404.2 - Web 服务扩展锁定策略阻止本请求。
    • 404.3 - MIME 映射策略阻止本请求。
  • 405 - 用来访问本页面的 HTTP 谓词不被允许(方法不被允许)
  • 406 - 客户端浏览器不接受所请求页面的 MIME 类型。
  • 407 - 要求进行代理身份验证。
  • 408 - 请求超时。
  • 409 - 由于和被请求的资源的当前状态之间存在冲突,请求无法完成。
  • 410 - 被请求的资源在服务器上已经不再可用,而且没有任何已知的转发地址。
  • 411 - 服务器拒绝在没有定义Content-Length头的情况下接受请求。
  • 412 - 前提条件失败。
  • 413 – 请求实体太大。
  • 414 - 请求 URI 太长。
  • 415 – 不支持的媒体类型。
  • 416 – 所请求的范围无法满足。
  • 417 – 执行失败。
  • 418 – 本操作码是在1998年作为IETF的传统愚人节笑话
  • 421 – 从当前客户端所在的IP地址到服务器的连接数超过了服务器许可的最大范围。
  • 422 – 请求格式正确,但是由于含有语义错误,无法响应。
  • 423 – 当前资源被锁定。
  • 424 – 由于之前的某个请求发生的错误,导致当前请求失败。
  • 425 – 无序的集合。
  • 426 – 客户端应当切换到TLS/1.0。
  • 451 – (由IETF在2015核准后新增加)该访问因法律的要求而被拒绝。

5xx服务器错误

这类状态码代表了服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。

  • 500 - 内部服务器错误。
  • 501 - 尚未实施,页眉值指定了未实现的配置。
  • 502 - 错误网关,Web 服务器用作网关或代理服务器时收到了无效响应。
  • 503 - 服务不可用,这个错误代码为 IIS 6.0 所专用。
  • 504 - 网关超时,服务器作为网关或代理,未及时从上游服务器接收请求。
  • 505 - HTTP 版本不受支持,服务器不支持请求中所使用的 HTTP 协议版本。
  • 506 - 服务器没有正确配置。
  • 507 - 存储空间不足。服务器无法存储完成请求所必须的内容。这个状况被认为是临时的。
  • 509 - 带宽超过限制。这不是一个官方的状态码,但是仍被广泛使用。
  • 510 - 没有扩展,获取资源所需要的策略并没有被满足。

FTP

1xx初步

肯定的初步答复,这些状态代码指示一项操作已经成功开始,但客户端希望在继续操作新命令前得到另一个答复。

  • 110 重新启动标记答复。
  • 120 服务已就绪,在 nnn 分钟后开始。
  • 125 数据连接已打开,正在开始传输。
  • 150 文件状态正常,准备打开数据连接。

2xx完成

肯定的完成答复,一项操作已经成功完成。客户端可以执行新命令。

  • 200 命令确定。
  • 202 未执行命令,站点上的命令过多。
  • 211 系统状态,或系统帮助答复。
  • 212 目录状态。
  • 213 文件状态。
  • 214 帮助消息。
  • 215 NAME 系统类型,其中,NAME 是 Assigned Numbers 文档中所列的正式系统名称。
  • 220 服务就绪,可以执行新用户的请求。
  • 221 服务关闭控制连接。如果适当,请注销。
  • 225 数据连接打开,没有进行中的传输。
  • 226 关闭数据连接。请求的文件操作已成功(例如,传输文件或放弃文件)。
  • 227 进入被动模式 (h1,h2,h3,h4,p1,p2)。
  • 230 用户已登录,继续进行。
  • 250 请求的文件操作正确,已完成。
  • 257 已创建“PATHNAME”。

3xx中间

肯定的中间答复,该命令已成功,但服务器需要更多来自客户端的信息以完成对请求的处理。

  • 331 用户名正确,需要密码。
  • 332 需要登录帐户。
  • 350 请求的文件操作正在等待进一步的信息。

4xx瞬态否定

瞬态否定的完成答复,该命令不成功,但错误是暂时的。如果客户端重试命令,可能会执行成功。

  • 421 服务不可用,正在关闭控制连接。如果服务确定它必须关闭,将向任何命令发送这一应答。
  • 425 无法打开数据连接。
  • 426 Connection closed; transfer aborted.
  • 450 未执行请求的文件操作。文件不可用(例如,文件繁忙)。
  • 451 请求的操作异常终止:正在处理本地错误。
  • 452 未执行请求的操作。系统存储空间不够。

5xx永久性否定

永久性否定的完成答复,该命令不成功,错误是永久性的。如果客户端重试命令,将再次出现同样的错误。

  • 500 语法错误,命令无法识别。这可能包括诸如命令行太长之类的错误。
  • 501 在参数中有语法错误。
  • 502 未执行命令。
  • 503 错误的命令序列。
  • 504 未执行该参数的命令。
  • 530 未登录。
  • 532 存储文件需要帐户。
  • 550 未执行请求的操作。文件不可用(例如,未找到文件,没有访问权限)。
  • 551 请求的操作异常终止:未知的页面类型。
  • 552 请求的文件操作异常终止:超出存储分配(对于当前目录或数据集)。
  • 553 未执行请求的操作。不允许的文件名。

6xx受保护

  • 600 Series,Replies regarding confidentiality and integrity
  • 631 Integrity protected reply.
  • 632 Confidentiality and integrity protected reply.
  • 633 Confidentiality protected reply.

WebSockets状态码

WebSockets 的CloseEvent 会在连接关闭时发送给使用 WebSockets 的客户端。它在 WebSocket 对象的 onclose 事件监听器中使用。服务端发送的关闭码,以下为已分配的状态码。

状态码 名称 描述
0–999 - 保留段, 未使用。
1000 CLOSE_NORMAL 正常关闭; 无论为何目的而创建, 该链接都已成功完成任务。
1001 CLOSE_GOING_AWAY 终端离开, 可能因为服务端错误, 也可能因为浏览器正从打开连接的页面跳转离开。
1002 CLOSE_PROTOCOL_ERROR 由于协议错误而中断连接。
1003 CLOSE_UNSUPPORTED 由于接收到不允许的数据类型而断开连接 (如仅接收文本数据的终端接收到了二进制数据)。
1004 - 保留。 其意义可能会在未来定义。
1005 CLOSE_NO_STATUS 保留。 表示没有收到预期的状态码。
1006 CLOSE_ABNORMAL 保留。 用于期望收到状态码时连接非正常关闭 (也就是说, 没有发送关闭帧)。
1007 Unsupported Data 由于收到了格式不符的数据而断开连接 (如文本消息中包含了非 UTF-8 数据)。
1008 Policy Violation 由于收到不符合约定的数据而断开连接。 这是一个通用状态码, 用于不适合使用 1003 和 1009 状态码的场景。
1009 CLOSE_TOO_LARGE 由于收到过大的数据帧而断开连接。
1010 Missing Extension 客户端期望服务器商定一个或多个拓展, 但服务器没有处理, 因此客户端断开连接。
1011 Internal Error 客户端由于遇到没有预料的情况阻止其完成请求, 因此服务端断开连接。
1012 Service Restart 服务器由于重启而断开连接。 [Ref]
1013 Try Again Later 服务器由于临时原因断开连接, 如服务器过载因此断开一部分客户端连接。 [Ref]
1014 - 由 WebSocket 标准保留以便未来使用。
1015 TLS Handshake 保留。 表示连接由于无法完成 TLS 握手而关闭 (例如无法验证服务器证书)。
1016–1999 - 由 WebSocket 标准保留以便未来使用。
2000–2999 - 由 WebSocket 拓展保留使用。
3000–3999 - 可以由库或框架使用。 不应由应用使用。 可以在 IANA 注册, 先到先得。
4000–4999 - 可以由应用使用。

参考资料

1. SSL 与 TLS

SSL:(Secure Socket Layer) 安全套接层,于 1994 年由网景公司设计,并于 1995 年发布了 3.0 版本
TLS:(Transport Layer Security)传输层安全性协议,是 IETF 在 SSL3.0 的基础上设计的协议
以下全部使用 TLS 来表示

2. 从网络协议的角度理解 HTTPS

此图并不准确
HTTP:HyperText Transfer Protocol 超文本传输协议
HTTPS:Hypertext Transfer Protocol Secure 超文本传输安全协议
TLS:位于 HTTP 和 TCP 之间的协议,其内部有 TLS握手协议、TLS记录协议
HTTPS 经由 HTTP 进行通信,但利用 TLS 来保证安全,即 HTTPS = HTTP + TLS

3. 从密码学的角度理解 HTTPS

HTTPS 使用 TLS 保证安全,这里的“安全”分两部分,一是传输内容加密、二是服务端的身份认证

3.1. TLS 工作流程

此图并不准确
此为服务端单向认证,还有客户端/服务端双向认证,流程类似,只不过客户端也有自己的证书,并发送给服务器进行验证

3.2. 密码基础

3.2.1. 伪随机数生成器

为什么叫伪随机数,因为没有真正意义上的随机数,具体可以参考 Random/TheadLocalRandom
它的主要作用在于生成对称密码的秘钥、用于公钥密码生成秘钥对

3.2.2. 消息认证码

消息认证码主要用于验证消息的完整性与消息的认证,其中消息的认证指“消息来自正确的发送者”

消息认证码用于验证和认证,而不是加密

消息认证码过程

  1. 发送者与接收者事先共享秘钥
  2. 发送者根据发送消息计算 MAC 值
  3. 发送者发送消息和 MAC 值
  4. 接收者根据接收到的消息计算 MAC 值
  5. 接收者根据自己计算的 MAC 值与收到的 MAC 对比
  6. 如果对比成功,说明消息完整,并来自与正确的发送者

3.2.3. 数字签名

消息认证码的缺点在于无法防止否认,因为共享秘钥被 client、server 两端拥有,server 可以伪造 client 发送给自己的消息(自己给自己发送消息),为了解决这个问题,我们需要它们有各自的秘钥不被第二个知晓(这样也解决了共享秘钥的配送问题)

数字签名过程

数字签名和消息认证码都不是为了加密
可以将单向散列函数获取散列值的过程理解为使用 md5 摘要算法获取摘要的过程

使用自己的私钥对自己所认可的消息生成一个该消息专属的签名,这就是数字签名,表明我承认该消息来自自己
注意:私钥用于加签,公钥用于解签,每个人都可以解签,查看消息的归属人

3.2.4. 公钥密码

公钥密码也叫非对称密码,由公钥和私钥组成,它是最开始是为了解决秘钥的配送传输安全问题,即,我们不配送私钥,只配送公钥,私钥由本人保管
它与数字签名相反,公钥密码的私钥用于解密、公钥用于加密,每个人都可以用别人的公钥加密,但只有对应的私钥才能解开密文
client:明文 + 公钥 = 密文
server:密文 + 私钥 = 明文
注意:公钥用于加密,私钥用于解密,只有私钥的归属者,才能查看消息的真正内容

3.2.5. 证书

证书:全称公钥证书(Public-Key Certificate, PKC),里面保存着归属者的基本信息,以及证书过期时间、归属者的公钥,并由认证机构(Certification Authority, CA)施加数字签名,表明,某个认证机构认定该公钥的确属于此人

想象这个场景:你想在支付宝页面交易,你需要支付宝的公钥进行加密通信,于是你从百度上搜索关键字“支付宝公钥”,你获得了支什宝的公钥,这个时候,支什宝通过中间人攻击,让你访问到了他们支什宝的页面,最后你在这个支什宝页面完美的使用了支什宝的公钥完成了与支什宝的交易
证书过程

在上面的场景中,你可以理解支付宝证书就是由支付宝的公钥、和给支付宝颁发证书的企业的数字签名组成
任何人都可以给自己或别人的公钥添加自己的数字签名,表明:我拿我的尊严担保,我的公钥/别人的公钥是真的,至于信不信那是另一回事了

3.2.6. 密码小结

密码 作用 组成
消息认证码 确认消息的完整、并对消息的来源认证 共享秘钥+消息的散列值
数字签名 对消息的散列值签名 公钥+私钥+消息的散列值
公钥密码 解决秘钥的配送问题 公钥+私钥+消息
证书 解决公钥的归属问题 公钥密码中的公钥+数字签名

3.3. TLS 使用的密码技术

  1. 伪随机数生成器:秘钥生成随机性,更难被猜测
  2. 对称密码:对称密码使用的秘钥就是由伪随机数生成,相较于非对称密码,效率更高
  3. 消息认证码:保证消息信息的完整性、以及验证消息信息的来源
  4. 公钥密码:证书技术使用的就是公钥密码
  5. 数字签名:验证证书的签名,确定由真实的某个 CA 颁发
  6. 证书:解决公钥的真实归属问题,降低中间人攻击概率

3.4. TLS 总结

TLS 是一系列密码工具的框架,作为框架,它也是非常的灵活,体现在每个工具套件它都可以替换,即:客户端与服务端之间协商密码套件,从而更难的被攻破,例如使用不同方式的对称密码,或者公钥密码、数字签名生成方式、单向散列函数技术的替换等

4. RSA 简单示例

RSA 是一种公钥密码算法,我们简单的走一遍它的加密解密过程
加密算法:密文 = (明文^E) mod N,其中公钥为{E,N},即”求明文的E次方的对 N 的余数“
解密算法:明文 = (密文^D) mod N,其中秘钥为{D,N},即”求密文的D次方的对 N 的余数“
例:我们已知公钥为{5,323},私钥为{29,323},明文为300,请写出加密和解密的过程:

加密:密文 = 123 ^ 5 mod 323 = 225
解密:明文 = 225 ^ 29 mod 323 = [[(225 ^ 5) mod 323] * [(225 ^ 5) mod 323] * [(225 ^ 5) mod 323] * [(225 ^ 5) mod 323] * [(225 ^ 5) mod 323] * [(225 ^ 4) mod 323]] mod 323 = (4 * 4 * 4 * 4 * 4 * 290) mod 323 = 123

5. 参考

  1. SSL加密发生在哪里:https://security.stackexchange.com/questions/19681/where-does-ssl-encryption-take-place
  2. TLS工作流程:https://blog.csdn.net/ustccw/article/details/76691248
  3. 《图解密码技术》:https://book.douban.com/subject/26822106/ 豆瓣评分 9.5

目录结构

1. 计算机概述

2. 物理层

3. 数据链路层

4. 网络层

5. 运输层

6. 应用层

一计算机概述

(1),基本术语

结点 (node):

网络中的结点可以是计算机,集线器,交换机或路由器等。
从一个结点到另一个结点的一段物理线路。中间没有任何其他交点。

主机(host):

连接在因特网上的计算机.

ISP(Internet Service Provider):

因特网服务提供者(提供商).

IXP(Internet eXchange Point):

互联网交换点IXP的主要作用就是允许两个网络直接相连并交换分组,而不需要再通过第三个网络来转发分组。.

RFC(Request For Comments)

意思是“请求评议”,包含了关于Internet几乎所有的重要的文字资料。

广域网WAN(Wide Area Network)

任务是通过长距离运送主机发送的数据

城域网MAN(Metropolitan Area Network)

用来讲多个局域网进行互连

局域网LAN(Local Area Network)

学校或企业大多拥有多个互连的局域网

个人区域网PAN(Personal Area Network)

在个人工作的地方把属于个人使用的电子设备用无线技术连接起来的网络  

端系统(end system):

处在因特网边缘的部分即是连接在因特网上的所有的主机.

分组(packet ):

因特网中传送的数据单元。由首部header和数据段组成。分组又称为包,首部可称为包头。

存储转发(store and forward ):

路由器收到一个分组,先存储下来,再检查气首部,查找转发表,按照首部中的目的地址,找到合适的接口转发出去。

带宽(bandwidth):

在计算机网络中,表示在单位时间内从网络中的某一点到另一点所能通过的“最高数据率”。常用来表示网络的通信线路所能传送数据的能力。单位是“比特每秒”,记为b/s。

吞吐量(throughput ):

表示在单位时间内通过某个网络(或信道、接口)的数据量。吞吐量更经常地用于对现实世界中的网络的一种测量,以便知道实际上到底有多少数据量能够通过网络。吞吐量受网络的带宽或网络的额定速率的限制。

(2),重要知识点总结

1,计算机网络(简称网络)把许多计算机连接在一起,而互联网把许多网络连接在一起,是网络的网络。

2,小写字母i开头的internet(互联网)是通用名词,它泛指由多个计算机网络相互连接而成的网络。在这些网络之间的通信协议(即通信规则)可以是任意的。

大写字母I开头的Internet(互联网)是专用名词,它指全球最大的,开放的,由众多网络相互连接而成的特定的互联网,并采用TCP/IP协议作为通信规则,其前身为ARPANET。Internet的推荐译名为因特网,现在一般流行称为互联网。

3,路由器是实现分组交换的关键构件,其任务是转发受到的分组,这是网络核心部分最重要的功能。分组交换采用存储转发技术,表示把一个报文(要发送的整块数据)分为几个分组后在进行传送。在发送报文之前,先把较长的报文划分成为一个个更小的等长数据段。在每个数据端的前面加上一些由必要的控制信息组成的首部后,就构成了一个分组。分组有称为包。分组是在互联网中传送的数据单元,正式由于分组的头部包含了诸如目的地址和源地址等重要控制信息,每一个分组才能在互联网中独立的选择传输路径,并正确地交付到分组传输的终点。

4,互联网按工作方式可划分为边缘部分和核心部分。主机在网络的边缘部分,其作用是进行信息处理。由大量网络和连接这些网络的路由西组成边缘部分,其作用是提供连通性和交换。

5,计算机通信是计算机中进程(即运行着的程序)之间的通信。计算机网络采用的通信方式是客户-服务器方式(C/S方式)和对等连接方式(P2P方式)。

6,客户和服务器都是指通信中所涉及的应用进程。客户是服务请求方,服务器是服务提供方。

7,按照作用范围的不同,计算机网络分为广域网WAN,城域网MAN,局域网LAN,个人区域网PAN。

8,计算机网络最常用的性能指标是:速率,带宽,吞吐量,时延(发送时延,处理时延,排队时延),时延带宽积,往返时间和信道利用率。

9,网络协议即协议,是为进行网络中的数据交换而建立的规则。计算机网络的各层以及其协议集合,称为网络的体系结构。

10,五层体系结构由应用层,运输层,网络层(网际层),数据链路层,物理层组成。运输层最主要的协议是TCP和UDP协议,网络层最重要的协议是IP协议。

二物理层

(1),基本术语

数据(data):

运送消息的实体。

信号(signal):

数据的电气的或电磁的表现。或者说信号是适合在传输介质上传输的对象。

码元( code):

在使用时间域(或简称为时域)的波形来表示数字信号时,代表不同离散数值的基本波形。

单工(simplex ):

只能有一个方向的通信而没有反方向的交互。

半双工(half duplex ):

通信的双方都可以发送信息,但不能双方同时发送(当然也就不能同时接收)。

全双工(full duplex):

通信的双方可以同时发送和接收信息。

奈氏准则:

在任何信道中,码元的传输的效率是有上限的,传输速率超过此上限,就会出现严重的码间串扰问题,使接收端对码元的判决(即识别)成为不可能。

基带信号(baseband signal):

来自信源的信号。指没有经过调制的数字信号或模拟信号。

带通(频带)信号(bandpass signal):

把基带信号经过载波调制后,把信号的频率范围搬移到较高的频段以便在信道中传输(即仅在一段频率范围内能够通过信道),这里调制过后的信号就是带通信号。

调制(modulation ):

对信号源的信息进行处理后加到载波信号上,使其变为适合在信道传输的形式的过程。

信噪比(signal-to-noise ratio ):

指信号的平均功率和噪声的平均功率之比,记为S/N。信噪比(dB)=10*log10(S/N)

信道复用(channel multiplexing ):

指多个用户共享同一个信道。(并不一定是同时)

比特率(bit rate ):

单位时间(每秒)内传送的比特数。

波特率(baud rate):

单位时间载波调制状态改变的次数。针对数据信号对载波的调制速率。

复用(multiplexing):

共享信道的方法

ADSL(Asymmetric Digital Subscriber Line ):

非对称数字用户线。

光纤同轴混合网(HFC网):

在目前覆盖范围很广的有线电视网的基础上开发的一种居民宽带接入网

(2),重要知识点总结

1,物理层的主要任务就是确定与传输媒体接口有关的一些特性,如机械特性,电气特性,功能特性,过程特性。

2,一个数据通信系统可划分为三大部分,即源系统,传输系统,目的系统。源系统包括源点(或源站,信源)和发送器,目的系统包括接收器和终点。

3,通信的目的是传送消息。如话音,文字,图像等都是消息,数据是运送消息的实体。信号则是数据的电器或电磁的表现。

4,根据信号中代表消息的参数的取值方式不同,信号可分为模拟信号(或连续信号)和数字信号(或离散信号)。在使用时间域(简称时域)的波形表示数字信号时,代表不同离散数值的基本波形称为码元。

5,根据双方信息交互的方式,通信可划分为单向通信(或单工通信),双向交替通信(或半双工通信),双向同时通信(全双工通信)。

6,来自信源的信号称为基带信号。信号要在信道上传输就要经过调制。调制有基带调制和带通调制之分。最基本的带通调制方法有调幅,调频和调相。还有更复杂的调制方法,如正交振幅调制。

7,要提高数据在信道上的传递速率,可以使用更好的传输媒体,或使用先进的调制技术。但数据传输速率不可能任意被提高。

8,传输媒体可分为两大类,即导引型传输媒体(双绞线,同轴电缆,光纤)和非导引型传输媒体(无线,红外,大气激光)。

9,为了有效利用光纤资源,在光纤干线和用户之间广泛使用无源光网络PON。无源光网络无需配备电源,其长期运营成本和管理成本都很低。最流行的无源光网络是以太网无源光网络EPON和吉比特无源光网络GPON。

(3),最重要的知识点

①,物理层的任务

透明地传送比特流。也可以将物理层的主要任务描述为确定与传输媒体的接口的一些特性,即:机械特性(接口所用接线器的一些物理属性如形状尺寸),电气特性(接口电缆的各条线上出现的电压的范围),功能特性(某条线上出现的某一电平的电压的意义),过程特性(对于不同功能能的各种可能事件的出现顺序)。

拓展:

物理层考虑的是怎样才能在连接各种计算机的传输媒体上传输数据比特流,而不是指具体的传输媒体。现有的计算机网络中的硬件设备和传输媒体的种类非常繁多,而且通信手段也有许多不同的方式。物理层的作用正是尽可能地屏蔽掉这些传输媒体和通信手段的差异,使物理层上面的数据链路层感觉不到这些差异,这样就可以使数据链路层只考虑完成本层的协议和服务,而不必考虑网络的具体传输媒体和通信手段是什么。

②,几种常用的信道复用技术

这里写图片描述

③,几种常用的宽带接入技术,主要是ADSL和FTTx

用户到互联网的宽带接入方法有非对称数字用户线ADSL(用数字技术对现有的模拟电话线进行改造,而不需要重新布线。ASDL的快速版本是甚高速数字用户线VDSL。),光纤同轴混合网HFC(是在目前覆盖范围很广的有线电视网的基础上开发的一种居民宽带接入网)和FTTx(即光纤到······)。

三数据链路层

(1),基本术语

链路(link):

一个结点到相邻结点的一段物理链路

数据链路(data link):

把实现控制数据运输的协议的硬件和软件加到链路上就构成了数据链路

循环冗余检验CRC(Cyclic Redundancy Check):

为了保证数据传输的可靠性,CRC是数据链路层广泛使用的一种检错技术

帧(frame):

一个数据链路层的传输单元,由一个数据链路层首部和其携带的封包所组成协议数据单元。

MTU(Maximum Transfer Uint ):

最大传送单元。帧的数据部分的的长度上限。

误码率BER(Bit Error Rate ):

在一段时间内,传输错误的比特占所传输比特总数的比率。

PPP(Point-to-Point Protocol ):

点对点协议。即用户计算机和ISP进行通信时所使用的数据链路层协议。以下是PPP帧的示意图:

PPP

MAC地址(Media Access Control或者Medium Access Control):

意译为媒体访问控制,或称为物理地址、硬件地址,用来定义网络设备的位置。
在OSI模型中,第三层网络层负责 IP地址,第二层数据链路层则负责 MAC地址。
因此一个主机会有一个MAC地址,而每个网络位置会有一个专属于它的IP地址  。
地址是识别某个系统的重要标识符,“名字指出我们所要寻找的资源,地址指出资源所在的地方,路由告诉我们如何到达该处”

网桥(bridge):

一种用于数据链路层实现中继,连接两个或多个局域网的网络互连设备。

交换机(switch ):

广义的来说,交换机指的是一种通信系统中完成信息交换的设备。这里工作在数据链路层的交换机指的是交换式集线器,其实质是一个多接口的网桥

(2),重要知识点总结

1,链路是从一个结点到相邻节点的一段物理链路,数据链路则在链路的基础上增加了一些必要的硬件(如网络适配器)和软件(如协议的实现)

2,数据链路层使用的主要是点对点信道广播信道两种。

3,数据链路层传输的协议数据单元是帧。数据链路层的三个基本问题是:封装成帧透明传输差错检测

4,循环冗余检验CRC是一种检错方法,而帧检验序列FCS是添加在数据后面的冗余码

5,点对点协议PPP是数据链路层使用最多的一种协议,它的特点是:简单,只检测差错而不去纠正差错,不使用序号,也不进行流量控制,可同时支持多种网络层协议

6,PPPoE是为宽带上网的主机使用的链路层协议

7,局域网的优点是:具有广播功能,从一个站点可方便地访问全网;便于系统的扩展和逐渐演变;提高了系统的可靠性,可用性和生存性。

8,共向媒体通信资源的方法有二:一是静态划分信道(各种复用技术),而是动态媒体接入控制,又称为多点接入(随即接入或受控接入)

9,计算机与外接局域网通信需要通过通信适配器(或网络适配器),它又称为网络接口卡或网卡。计算器的硬件地址就在适配器的ROM中

10,以太网采用的无连接的工作方式,对发送的数据帧不进行编号,也不要求对方发回确认。目的站收到有差错帧就把它丢掉,其他什么也不做

11,以太网采用的协议是具有冲突检测的载波监听多点接入CSMA/CD。协议的特点是:发送前先监听,边发送边监听,一旦发现总线上出现了碰撞,就立即停止发送。然后按照退避算法等待一段随机时间后再次发送。 因此,每一个站点在自己发送数据之后的一小段时间内,存在这遭遇碰撞的可能性。以太网上的各站点平等的争用以太网信道

12,以太网的适配器具有过滤功能,它只接收单播帧,广播帧和多播帧。

13,使用集线器可以在物理层扩展以太网(扩展后的以太网任然是一个网络)

(3),最重要的知识点

数据链路层的点对点信道和广播信道的特点,以及这两种信道所使用的协议(PPP协议以及CSMA/CD协议)的特点

数据链路层的三个基本问题:封装成帧透明传输差错检测

以太网的MAC层硬件地址

适配器,转发器,集线器,网桥,以太网交换机的作用以及适用场合

四网络层

(1),基本术语

虚电路(Virtual Circuit):

在两个终端设备的逻辑或物理端口之间,通过建立的双向的透明传输通道。虚电路表示这只是一条逻辑上的连接,分组都沿着这条逻辑连接按照存储转发方式传送,而并不是真正建立了一条物理连接。

IP(Internet Protocol ):

网际协议 IP 是 TCP/IP体系中两个最主要的协议之一,是TCP/IP体系结构网际层的核心。配套的有ARP,RARP,ICMP,IGMP。

这里写图片描述

ARP(Address Resolution Protocol):

地址解析协议

ICMP(Internet Control Message Protocol ):

网际控制报文协议  (ICMP 允许主机或路由器报告差错情况和提供有关异常情况的报告。)

子网掩码(subnet mask ):

它是一种用来指明一个IP地址的哪些位标识的是主机所在的子网以及哪些位标识的是主机的位掩码。子网掩码不能单独存在,它必须结合IP地址一起使用。

CIDR( Classless Inter-Domain Routing ):

无分类域间路由选择  (特点是消除了传统的 A 类、B 类和 C 类地址以及划分子网的概念,并使用各种长度的“网络前缀”(network-prefix)来代替分类地址中的网络号和子网号)

默认路由(default route):

当在路由表中查不到能到达目的地址的路由时,路由器选择的路由。默认路由还可以减小路由表所占用的空间和搜索路由表所用的时间。

路由选择算法(Virtual Circuit):

路由选择协议的核心部分。因特网采用自适应的,分层次的路由选择协议。

(2),重要知识点总结

1,TCP/IP协议中的网络层向上只提供简单灵活的,无连接的,尽最大努力交付的数据报服务。网络层不提供服务质量的承诺,不保证分组交付的时限所传送的分组可能出错,丢失,重复和失序。进程之间通信的可靠性由运输层负责

2,在互联网的交付有两种,一是在本网络直接交付不用经过路由器,另一种是和其他网络的间接交付,至少经过一个路由器,但最后一次一定是直接交付

3,分类的IP地址由网络号字段(指明网络)和主机号字段(指明主机)组成。网络号字段最前面的类别指明IP地址的类别。IP地址市一中分等级的地址结构。IP地址管理机构分配IP地址时只分配网络号,主机号由得到该网络号的单位自行分配。路由器根据目的主机所连接的网络号来转发分组。一个路由器至少连接到两个网络,所以一个路由器至少应当有两个不同的IP地址

4,IP数据报分为首部和数据两部分。首部的前一部分是固定长度,共20字节,是所有IP数据包必须具有的(源地址,目的地址,总长度等重要地段都固定在首部)。一些长度可变的可选字段固定在首部的后面。IP首部中的生存时间给出了IP数据报在互联网中所能经过的最大路由器数。可防止IP数据报在互联网中无限制的兜圈子。

5,地址解析协议ARP把IP地址解析为硬件地址。ARP的高速缓存可以大大减少网络上的通信量。因为这样可以使主机下次再与同样地址的主机通信时,可以直接从高速缓存中找到所需要的硬件地址而不需要再去广播方式发送ARP请求分组

6,无分类域间路由选择CIDR是解决目前IP地址紧缺的一个好办法。CIDR记法把IP地址后面加上斜线“/”,然后写上前缀所所占的位数。前缀(或网络前缀用来指明网络),前缀后面的部分是后缀,用来指明主机。CIDR把前缀都相同的连续的IP地址组成一个“CIDR地址块”,IP地址分配都以CIDR地址块为单位。

7, 网际控制报文协议是IP层的协议.ICMP报文作为IP数据报的数据,加上首部后组成IP数据报发送出去。使用ICMP数据报并不是为了实现可靠传输。ICMP允许主机或路由器报告差错情况和提供有关异常情况的报告。ICMP报文的种类有两种 ICMP差错报告报文和ICMP询问报文。

8,要解决IP地址耗尽的问题,最根本的办法是采用具有更大地址弓箭的新版本IP协议-IPv6。IPv6所带来的变化有①更大的地址空间(采用128位地址)②灵活的首部格式③改进的选项④支持即插即用⑤支持资源的预分配⑥IPv6的首部改为8字节对齐。另外IP数据报的目的地址可以是以下三种基本类型地址之一:单播,多播和任播

9,虚拟专用网络VPN利用公用的互联网作为本机构专用网之间的通信载体。VPN内使用互联网的专用地址。一个VPN至少要有一个路由器具有合法的全球IP地址,这样才能和本系统的另一个VPN通过互联网进行通信。所有通过互联网传送的数据都需要加密

10, MPLS的特点是:①支持面向连接的服务质量②支持流量工程,平衡网络负载③有效的支持虚拟专用网VPN。MPLS在入口节点给每一个IP数据报打上固定长度的“标记”,然后根据标记在第二层(链路层)用硬件进行转发(在标记交换路由器中进行标记交换),因而转发速率大大加快。

(3),最重要知识点

虚拟互联网络的概念

IP地址和物理地址的关系

传统的分类的IP地址(包括子网掩码)和误分类域间路由选择CIDR

路由选择协议的工作原理

五运输层

(1),基本术语

进程(process):

指计算机中正在运行的程序实体

应用进程互相通信:

一台主机的进程和另一台主机中的一个进程交换数据的过程(另外注意通信真正的端点不是主机而是主机中的进程,也就是说端到端的通信是应用进程之间的通信)

传输层的复用与分用:

复用指发送方不同的进程都可以通过统一个运输层协议传送数据。分用指接收方的运输层在剥去报文的首部后能把这些数据正确的交付到目的应用进程。 

TCP(Transmission Control Protocol):

传输控制协议

UDP(User Datagram Protocol):

用户数据报协议

端口(port)(link):

端口的目的是为了确认对方机器是那个进程在于自己进行交互,比如MSN和QQ的端口不同,如果没有端口就可能出现QQ进程和MSN交互错误。端口又称协议端口号。 

停止等待协议(link):

指发送方每发送完一个分组就停止发送,等待对方确认,在收到确认之后在发送下一个分组。

流量控制(link):

就是让发送方的发送速率不要太快,既要让接收方来得及接收,也不要使网络发生拥塞。

拥塞控制(link):

防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。

(2),重要知识点总结

1,运输层提供应用进程之间的逻辑通信,也就是说,运输层之间的通信并不是真正在两个运输层之间直接传输数据。运输层向应用层屏蔽了下面网络的细节(如网络拓补,所采用的路由选择协议等),它使应用进程之间看起来好像两个运输层实体之间有一条端到端的逻辑通信信道。

2,网络层为主机提供逻辑通信,而运输层为应用进程之间提供端到端的逻辑通信。

3,运输层的两个重要协议是用户数据报协议UDP和传输控制协议TCP。按照OSI的术语,两个对等运输实体在通信时传送的数据单位叫做运输协议数据单元TPDU(Transport Protocol Data Unit)。但在TCP/IP体系中,则根据所使用的协议是TCP或UDP,分别称之为TCP报文段或UDP用户数据报。

4,UDP在传送数据之前不需要先建立连接,远地主机在收到UDP报文后,不需要给出任何确认。虽然UDP不提供可靠交付,但在某些情况下UDP确是一种最有效的工作方式。 TCP提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。TCP不提供广播或多播服务。由于TCP要提供可靠的,面向连接的传输服务,这一难以避免增加了许多开销,如确认,流量控制,计时器以及连接管理等。这不仅使协议数据单元的首部增大很多,还要占用许多处理机资源。

5,硬件端口是不同硬件设备进行交互的接口,而软件端口是应用层各种协议进程与运输实体进行层间交互的一种地址。UDP和TCP的首部格式中都有源端口和目的端口这两个重要字段。当运输层收到IP层交上来的运输层报文时,就能够 根据其首部中的目的端口号把数据交付应用层的目的应用层。(两个进程之间进行通信不光要知道对方IP地址而且要知道对方的端口号(为了找到对方计算机中的应用进程))

6,运输层用一个16位端口号标志一个端口。端口号只有本地意义,它只是为了标志计算机应用层中的各个进程在和运输层交互时的层间接口。在互联网的不同计算机中,相同的端口号是没有关联的。协议端口号简称端口。虽然通信的终点是应用进程,但只要把所发送的报文交到目的主机的某个合适端口,剩下的工作(最后交付目的进程)就由TCP和UDP来完成。

7,运输层的端口号分为服务器端使用的端口号(01023指派给熟知端口,102449151是登记端口号)和客户端暂时使用的端口号(49152~65535)

8,UDP的主要特点是①无连接②尽最大努力交付③面向报文④无拥塞控制⑤支持一对一,一对多,多对一和多对多的交互通信⑥首部开销小(只有四个字段:源端口,目的端口,长度和检验和)

9,TCP的主要特点是①面向连接②每一条TCP连接只能是一对一的③提供可靠交付④提供全双工通信⑤面向字节流

10,TCP用主机的IP地址加上主机上的端口号作为TCP连接的端点。这样的端点就叫做套接字(socket)或插口。套接字用(IP地址:端口号)来表示。每一条TCP连接唯一被通信两端的两个端点所确定。

11,停止等待协议是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组。

12,为了提高传输效率,发送方可以不使用低效率的停止等待协议,而是采用流水线传输。流水线传输就是发送方可连续发送多个分组,不必每发完一个分组就停下来等待对方确认。这样可使信道上一直有数据不间断的在传送。这种传输方式可以明显提高信道利用率。

13,停止等待协议中超时重传是指只要超过一段时间仍然没有收到确认,就重传前面发送过的分组(认为刚才发送过的分组丢失了)。因此每发送完一个分组需要设置一个超时计时器,其重转时间应比数据在分组传输的平均往返时间更长一些。这种自动重传方式常称为自动重传请求ARQ。另外在停止等待协议中若收到重复分组,就丢弃该分组,但同时还要发送确认。连续ARQ协议可提高信道利用率。发送维持一个发送窗口,凡位于发送窗口内的分组可连续发送出去,而不需要等待对方确认。接收方一般采用累积确认,对按序到达的最后一个分组发送确认,表明到这个分组位置的所有分组都已经正确收到了。

14,TCP报文段的前20个字节是固定的,后面有4n字节是根据需要增加的选项。因此,TCP首部的最小长度是20字节。

15,TCP使用滑动窗口机制。发送窗口里面的序号表示允许发送的序号。发送窗口后沿的后面部分表示已发送且已收到确认,而发送窗口前沿的前面部分表示不晕与发送。发送窗口后沿的变化情况有两种可能,即不动(没有收到新的确认)和前移(收到了新的确认)。发送窗口的前沿通常是不断向前移动的。一般来说,我们总是希望数据传输更快一些。但如果发送方把数据发送的过快,接收方就可能来不及接收,这就会造成数据的丢失。所谓流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。

16,在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。

17,为了进行拥塞控制,TCP发送方要维持一个拥塞窗口cwnd的状态变量。拥塞控制窗口的大小取决于网络的拥塞程度,并且动态变化。发送方让自己的发送窗口取为拥塞窗口和接收方的接受窗口中较小的一个。

18,TCP的拥塞控制采用了四种算法,即慢开始,拥塞避免,快重传和快恢复。在网络层也可以使路由器采用适当的分组丢弃策略(如主动队列管理AQM),以减少网络拥塞的发生。

19,运输连接的三个阶段,即:连接建立,数据传送和连接释放。

20,主动发起TCP连接建立的应用进程叫做客户,而被动等待连接建立的应用进程叫做服务器。TCP连接采用三报文握手机制。服务器要确认用户的连接请求,然后客户要对服务器的确认进行确认。

21,TCP的连接释放采用四报文握手机制。任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送时,则发送连接释放通知,对方确认后就完全关闭了TCP连接

(3),最重要的知识点

端口和套接字的意义

无连接UDP的特点

面向连接TCP的特点

在不可靠的网络上实现可靠传输的工作原理,停止等待协议和ARQ协议

TCP的滑动窗口,流量控制,拥塞控制和连接管理

六应用层

(1),基本术语

域名系统(DNS):

DNS(Domain Name System,域名系统),万维网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。
通过域名,最终得到该域名对应的IP地址的过程叫做域名解析(或主机名解析)。DNS协议运行在UDP协议之上,使用端口号53。在RFC文档中RFC 2181对DNS有规范说明,RFC 2136对DNS的动态更新进行说明,RFC 2308对DNS查询的反向缓存进行说明。

文件传输协议(FTP):

FTP 是File TransferProtocol(文件传输协议)的英文简称,而中文简称为“文传协议”。用于Internet上的控制文件的双向传输。同时,它也是一个应用程序(Application)。
基于不同的操作系统有不同的FTP应用程序,而所有这些应用程序都遵守同一种协议以传输文件。在FTP的使用当中,用户经常遇到两个概念:"下载"(Download)和"上传"(Upload)。
"下载"文件就是从远程主机拷贝文件至自己的计算机上;"上传"文件就是将文件从自己的计算机中拷贝至远程主机上。用Internet语言来说,用户可通过客户机程序向(从)远程主机上传(下载)文件。

简单文件传输协议(TFTP):

TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。端口号为69。

远程终端协议(TELENET):

Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式。它为用户提供了在本地计算机上完成远程主机工作的能力。
在终端使用者的电脑上使用telnet程序,用它连接到服务器。终端使用者可以在telnet程序中输入命令,这些命令会在服务器上运行,就像直接在服务器的控制台上输入一样。
可以在本地就能控制服务器。要开始一个telnet会话,必须输入用户名和密码来登录服务器。Telnet是常用的远程控制Web服务器的方法。

万维网(WWW):

WWW是环球信息网的缩写,(亦作“Web”、“WWW”、“'W3'”,英文全称为“World Wide Web”),中文名字为“万维网”,"环球网"等,常简称为Web。分为Web客户端和Web服务器程序。
WWW可以让Web客户端(常用浏览器)访问浏览Web服务器上的页面。是一个由许多互相链接的超文本组成的系统,通过互联网访问。在这个系统中,每个有用的事物,称为一样“资源”;并且由一个全局“统一资源标识符”(URI)标识;这些资源通过超文本传输协议(Hypertext Transfer Protocol)传送给用户,而后者通过点击链接来获得资源。
万维网联盟(英语:World Wide Web Consortium,简称W3C),又称W3C理事会。1994年10月在麻省理工学院(MIT)计算机科学实验室成立。万维网联盟的创建者是万维网的发明者蒂姆·伯纳斯-李。
万维网并不等同互联网,万维网只是互联网所能提供的服务其中之一,是靠着互联网运行的一项服务。

万维网的大致工作工程:

万维网的大致工作工程

统一资源定位符(URL):

统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。 

超文本传输协议(HTTP):

超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。
设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。1960年美国人Ted Nelson构思了一种通过计算机处理文本信息的方法,并称之为超文本(hypertext),这成为了HTTP超文本传输协议标准架构的发展根基。

代理服务器(Proxy Server):

代理服务器(Proxy Server)是一种网络实体,它又称为万维网高速缓存。
代理服务器把最近的一些请求和响应暂存在本地磁盘中。当新请求到达时,若代理服务器发现这个请求与暂时存放的的请求相同,就返回暂存的响应,而不需要按URL的地址再次去互联网访问该资源。
代理服务器可在客户端或服务器工作,也可以在中间系统工作。 

http请求头:

http请求头,HTTP客户程序(例如浏览器),向服务器发送请求的时候必须指明请求类型(一般是GET或者POST)。如有必要,客户程序还可以选择发送其他的请求头。
- Accept:浏览器可接受的MIME类型。
- Accept-Charset:浏览器可接受的字符集。
- Accept-Encoding:浏览器能够进行解码的数据编码方式,比如gzip。Servlet能够向支持gzip的浏览器返回经gzip编码的HTML页面。许多情形下这可以减少5到10倍的下载时间。
- Accept-Language:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到。
- Authorization:授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中。
- Connection:表示是否需要持久连接。如果Servlet看到这里的值为“Keep-Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一点,Servlet需要在应答中发送一个Content-Length头,最简单的实现方法是:先把内容写入ByteArrayOutputStream,然后在正式写出内容之前计算它的大小。
- Content-Length:表示请求消息正文的长度。
- Cookie:这是最重要的请求头信息之一
- From:请求发送者的email地址,由一些特殊的Web客户程序使用,浏览器不会用到它。
- Host:初始URL中的主机和端口。
- If-Modified-Since:只有当所请求的内容在指定的日期之后又经过修改才返回它,否则返回304“Not Modified”应答。
- Pragma:指定“no-cache”值表示服务器必须返回一个刷新后的文档,即使它是代理服务器而且已经有了页面的本地拷贝。
- Referer:包含一个URL,用户从该URL代表的页面出发访问当前请求的页面。
- User-Agent:浏览器类型,如果Servlet返回的内容与浏览器类型有关则该值非常有用。

简单邮件传输协议(SMTP):

SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。
SMTP协议属于TCP/IP协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。
通过SMTP协议所指定的服务器,就可以把E-mail寄到收信人的服务器上了,整个过程只要几分钟。SMTP服务器则是遵循SMTP协议的发送邮件服务器,用来发送或中转发出的电子邮件。

搜索引擎:

搜索引擎(Search Engine)是指根据一定的策略、运用特定的计算机程序从互联网上搜集信息,在对信息进行组织和处理后,为用户提供检索服务,将用户检索相关的信息展示给用户的系统。
搜索引擎包括全文索引、目录索引、元搜索引擎、垂直搜索引擎、集合式搜索引擎、门户搜索引擎与免费链接列表等。

全文索引:

 全文索引技术是目前搜索引擎的关键技术。
试想在1M大小的文件中搜索一个词,可能需要几秒,在100M的文件中可能需要几十秒,如果在更大的文件中搜索那么就需要更大的系统开销,这样的开销是不现实的。
所以在这样的矛盾下出现了全文索引技术,有时候有人叫倒排文档技术。

目录索引:

目录索引( search index/directory),顾名思义就是将网站分门别类地存放在相应的目录中,因此用户在查询信息时,可选择关键词搜索,也可按分类目录逐层查找。

垂直搜索引擎:

垂直搜索引擎是针对某一个行业的专业搜索引擎,是搜索引擎的细分和延伸,是对网页库中的某类专门的信息进行一次整合,定向分字段抽取出需要的数据进行处理后再以某种形式返回给用户。
垂直搜索是相对通用搜索引擎的信息量大、查询不准确、深度不够等提出来的新的搜索引擎服务模式,通过针对某一特定领域、某一特定人群或某一特定需求提供的有一定价值的信息和相关服务。
其特点就是“专、精、深”,且具有行业色彩,相比较通用搜索引擎的海量信息无序化,垂直搜索引擎则显得更加专注、具体和深入。

(2),重要知识点总结

1,文件传输协议(FTP)使用TCP可靠的运输服务。FTP使用客户服务器方式。一个FTP服务器进程可以同时为多个用户提供服务。在进进行文件传输时,FTP的客户和服务器之间要先建立两个并行的TCP连接:控制连接和数据连接。实际用于传输文件的是数据连接。

2,万维网客户程序与服务器之间进行交互使用的协议时超文本传输协议HTTP。HTTP使用TCP连接进行可靠传输。但HTTP本身是无连接、无状态的。HTTP/1.1协议使用了持续连接(分为非流水线方式和流水线方式)

3,电子邮件把邮件发送到收件人使用的邮件服务器,并放在其中的收件人邮箱中,收件人可随时上网到自己使用的邮件服务器读取,相当于电子邮箱。

4,一个电子邮件系统有三个重要组成构件:用户代理、邮件服务器、邮件协议(包括邮件发送协议,如SMTP,和邮件读取协议,如POP3和IMAP)。用户代理和邮件服务器都要运行这些协议。

(3),最重要知识点总结

域名系统-从域名解析出IP地址

访问一个网站大致的过程

系统调用和应用编程接口概念

相对与上一个版本的计算机网路面试知识总结,这个版本增加了 “TCP协议如何保证可靠传输”包括超时重传、停止等待协议、滑动窗口、流量控制、拥塞控制等内容并且对一些已有内容做了补充。

一 OSI与TCP/IP各层的结构与功能,都有哪些协议

五层协议的体系结构

学习计算机网络时我们一般采用折中的办法,也就是中和 OSI 和 TCP/IP 的优点,采用一种只有五层协议的体系结构,这样既简洁又能将概念阐述清楚。

五层协议的体系结构

结合互联网的情况,自上而下地,非常简要的介绍一下各层的作用。

1 应用层

应用层(application-layer)的任务是通过应用进程间的交互来完成特定网络应用。应用层协议定义的是应用进程(进程:主机中正在运行的程序)间的通信和交互的规则。对于不同的网络应用需要不同的应用层协议。在互联网中应用层协议很多,如域名系统DNS,支持万维网应用的 HTTP协议,支持电子邮件的 SMTP协议等等。我们把应用层交互的数据单元称为报文。

域名系统

域名系统(Domain Name System缩写 DNS,Domain Name被译为域名)是因特网的一项核心服务,它作为可以将域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。(百度百科)例如:一个公司的 Web 网站可看作是它在网上的门户,而域名就相当于其门牌地址,通常域名都使用该公司的名称或简称。例如上面提到的微软公司的域名,类似的还有:IBM 公司的域名是 www.ibm.com、Oracle 公司的域名是 www.oracle.com、Cisco公司的域名是 www.cisco.com 等。

HTTP协议

超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的 WWW(万维网) 文件都必须遵守这个标准。设计 HTTP 最初的目的是为了提供一种发布和接收 HTML 页面的方法。(百度百科)

2 运输层

运输层(transport layer)的主要任务就是负责向两台主机进程之间的通信提供通用的数据传输服务。应用进程利用该服务传送应用层报文。“通用的”是指并不针对某一个特定的网络应用,而是多种应用可以使用同一个运输层服务。由于一台主机可同时运行多个线程,因此运输层有复用和分用的功能。所谓复用就是指多个应用层进程可同时使用下面运输层的服务,分用和复用相反,是运输层把收到的信息分别交付上面应用层中的相应进程。

运输层主要使用以下两种协议

  1. 传输控制协议 TCP(Transmission Control Protocol)–提供面向连接的,可靠的数据传输服务。
  2. 用户数据协议 UDP(User Datagram Protocol)–提供无连接的,尽最大努力的数据传输服务(不保证数据传输的可靠性)。

UDP 的主要特点

  1. UDP 是无连接的;
  2. UDP 使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态(这里面有许多参数);
  3. UDP 是面向报文的;
  4. UDP 没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如 直播,实时视频会议等);
  5. UDP 支持一对一、一对多、多对一和多对多的交互通信;
  6. UDP 的首部开销小,只有8个字节,比TCP的20个字节的首部要短。

TCP 的主要特点

  1. TCP 是面向连接的。(就好像打电话一样,通话前需要先拨号建立连接,通话结束后要挂机释放连接);
  2. 每一条 TCP 连接只能有两个端点,每一条TCP连接只能是点对点的(一对一);
  3. TCP 提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序到达;
  4. TCP 提供全双工通信。TCP 允许通信双方的应用进程在任何时候都能发送数据。TCP 连接的两端都设有发送缓存和接收缓存,用来临时存放双方通信的数据;
  5. 面向字节流。TCP 中的“流”(Stream)指的是流入进程或从进程流出的字节序列。“面向字节流”的含义是:虽然应用程序和 TCP 的交互是一次一个数据块(大小不等),但 TCP 把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。

3 网络层

在 计算机网络中进行通信的两个计算机之间可能会经过很多个数据链路,也可能还要经过很多通信子网。网络层的任务就是选择合适的网间路由和交换结点, 确保数据及时传送。 在发送数据时,网络层把运输层产生的报文段或用户数据报封装成分组和包进行传送。在 TCP/IP 体系结构中,由于网络层使用 IP 协议,因此分组也叫 IP 数据报 ,简称 数据报

这里要注意:不要把运输层的“用户数据报 UDP ”和网络层的“ IP 数据报”弄混。另外,无论是哪一层的数据单元,都可笼统地用“分组”来表示。

这里强调指出,网络层中的“网络”二字已经不是我们通常谈到的具体网络,而是指计算机网络体系结构模型中第三层的名称.

互联网是由大量的异构(heterogeneous)网络通过路由器(router)相互连接起来的。互联网使用的网络层协议是无连接的网际协议(Intert Protocol)和许多路由选择协议,因此互联网的网络层也叫做网际层IP层

4 数据链路层

数据链路层(data link layer)通常简称为链路层。两台主机之间的数据传输,总是在一段一段的链路上传送的,这就需要使用专门的链路层的协议。 在两个相邻节点之间传送数据时,数据链路层将网络层交下来的 IP 数据报组装程帧,在两个相邻节点间的链路上传送帧。每一帧包括数据和必要的控制信息(如同步信息,地址信息,差错控制等)。

在接收数据时,控制信息使接收端能够知道一个帧从哪个比特开始和到哪个比特结束。这样,数据链路层在收到一个帧后,就可从中提出数据部分,上交给网络层。
控制信息还使接收端能够检测到所收到的帧中有误差错。如果发现差错,数据链路层就简单地丢弃这个出了差错的帧,以避免继续在网络中传送下去白白浪费网络资源。如果需要改正数据在链路层传输时出现差错(这就是说,数据链路层不仅要检错,而且还要纠错),那么就要采用可靠性传输协议来纠正出现的差错。这种方法会使链路层的协议复杂些。

5 物理层

在物理层上所传送的数据单位是比特。
物理层(physical layer)的作用是实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异。 使其上面的数据链路层不必考虑网络的具体传输介质是什么。“透明传送比特流”表示经实际电路传送后的比特流没有发生变化,对传送的比特流来说,这个电路好像是看不见的。

在互联网使用的各种协中最重要和最著名的就是 TCP/IP 两个协议。现在人们经常提到的TCP/IP并不一定单指TCP和IP这两个具体的协议,而往往表示互联网所使用的整个TCP/IP协议族。

总结一下

上面我们对计算机网络的五层体系结构有了初步的了解,下面附送一张七层体系结构图总结一下。图片来源:https://blog.csdn.net/yaopeng_2005/article/details/7064869
七层体系结构图

二 TCP 三次握手和四次挥手(面试常客)

为了准确无误地把数据送达目标处,TCP协议采用了三次握手策略。

漫画图解:

图片来源:《图解HTTP》
TCP三次握手

简单示意图:
TCP三次握手

  • 客户端–发送带有 SYN 标志的数据包–一次握手–服务端
  • 服务端–发送带有 SYN/ACK 标志的数据包–二次握手–客户端
  • 客户端–发送带有带有 ACK 标志的数据包–三次握手–服务端

为什么要三次握手

三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。

第一次握手:Client 什么都不能确认;Server 确认了对方发送正常

第二次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己接收正常,对方发送正常

第三次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己发送、接收正常,对方发送、接收正常

所以三次握手就能确认双发收发功能都正常,缺一不可。

为什么要传回 SYN

接收端传回发送端所发送的 SYN 是为了告诉发送端,我接收到的信息确实就是你所发送的信号了。

SYN 是 TCP/IP 建立连接时使用的握手信号。在客户机和服务器之间建立正常的 TCP 网络连接时,客户机首先发出一个 SYN 消息,服务器使用 SYN-ACK 应答表示接收到了这个消息,最后客户机再以 ACK(Acknowledgement[汉译:确认字符 ,在数据通信传输中,接收站发给发送站的一种传输控制字符。它表示确认发来的数据已经接受无误。 ])消息响应。这样在客户机和服务器之间才能建立起可靠的TCP连接,数据才可以在客户机和服务器之间传递。

传了 SYN,为啥还要传 ACK

双方通信无误必须是两者互相发送信息都无误。传了 SYN,证明发送方到接收方的通道没有问题,但是接收方到发送方的通道还需要 ACK 信号来进行验证。

TCP四次挥手

断开一个 TCP 连接则需要“四次挥手”:

  • 客户端-发送一个 FIN,用来关闭客户端到服务器的数据传送
  • 服务器-收到这个 FIN,它发回一 个 ACK,确认序号为收到的序号加1 。和 SYN 一样,一个 FIN 将占用一个序号
  • 服务器-关闭与客户端的连接,发送一个FIN给客户端
  • 客户端-发回 ACK 报文确认,并将确认序号设置为收到序号加1

为什么要四次挥手

任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了TCP连接。

举个例子:A 和 B 打电话,通话即将结束后,A 说“我没啥要说的了”,B回答“我知道了”,但是 B 可能还会有要说的话,A 不能要求 B 跟着自己的节奏结束通话,于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”,A 回答“知道了”,这样通话才算结束。

上面讲的比较概括,推荐一篇讲的比较细致的文章:https://blog.csdn.net/qzcsu/article/details/72861891

三 TCP、UDP 协议的区别

TCP、UDP协议的区别

UDP 在传送数据之前不需要先建立连接,远地主机在收到 UDP 报文后,不需要给出任何确认。虽然 UDP 不提供可靠交付,但在某些情况下 UDP 确是一种最有效的工作方式(一般用于即时通信),比如: QQ 语音、 QQ 视频 、直播等等

TCP 提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。 TCP 不提供广播或多播服务。由于 TCP 要提供可靠的,面向连接的传输服务(TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源),这一难以避免增加了许多开销,如确认,流量控制,计时器以及连接管理等。这不仅使协议数据单元的首部增大很多,还要占用许多处理机资源。TCP 一般用于文件传输、发送和接收邮件、远程登录等场景。

四 TCP 协议如何保证可靠传输

  1. 应用数据被分割成 TCP 认为最适合发送的数据块。
  2. TCP 给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。
  3. 校验和: TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。
  4. TCP 的接收端会丢弃重复的数据。
  5. 流量控制: TCP 连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议。 (TCP 利用滑动窗口实现流量控制)
  6. 拥塞控制: 当网络拥塞时,减少数据的发送。
  7. 停止等待协议 也是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组。
  8. 超时重传: 当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。

停止等待协议

  • 停止等待协议是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组;
  • 在停止等待协议中,若接收方收到重复分组,就丢弃该分组,但同时还要发送确认;

1) 无差错情况:

发送方发送分组,接收方在规定时间内收到,并且回复确认.发送方再次发送。

2) 出现差错情况(超时重传):

停止等待协议中超时重传是指只要超过一段时间仍然没有收到确认,就重传前面发送过的分组(认为刚才发送过的分组丢失了)。因此每发送完一个分组需要设置一个超时计时器,其重转时间应比数据在分组传输的平均往返时间更长一些。这种自动重传方式常称为 自动重传请求 ARQ 。另外在停止等待协议中若收到重复分组,就丢弃该分组,但同时还要发送确认。连续 ARQ 协议 可提高信道利用率。发送维持一个发送窗口,凡位于发送窗口内的分组可连续发送出去,而不需要等待对方确认。接收方一般采用累积确认,对按序到达的最后一个分组发送确认,表明到这个分组位置的所有分组都已经正确收到了。

3) 确认丢失和确认迟到

  • 确认丢失:确认消息在传输过程丢失

    当A发送M1消息,B收到后,B向A发送了一个M1确认消息,但却在传输过程中丢失。而A并不知道,在超时计时过后,A重传M1消息,B再次收到该消息后采取以下两点措施:

    1. 丢弃这个重复的M1消息,不向上层交付。
    2. 向A发送确认消息。(不会认为已经发送过了,就不再发送。A能重传,就证明B的确认消息丢失)。
  • 确认迟到 :确认消息在传输过程中迟到

    A发送M1消息,B收到并发送确认。在超时时间内没有收到确认消息,A重传M1消息,B仍然收到并继续发送确认消息(B收到了2份M1)。此时A收到了B第二次发送的确认消息。接着发送其他数据。过了一会,A收到了B第一次发送的对M1的确认消息(A也收到了2份确认消息)。处理如下:

    1. A收到重复的确认后,直接丢弃。
    2. B收到重复的M1后,也直接丢弃重复的M1。

自动重传请求 ARQ 协议

停止等待协议中超时重传是指只要超过一段时间仍然没有收到确认,就重传前面发送过的分组(认为刚才发送过的分组丢失了)。因此每发送完一个分组需要设置一个超时计时器,其重传时间应比数据在分组传输的平均往返时间更长一些。这种自动重传方式常称为自动重传请求ARQ。

优点: 简单

缺点: 信道利用率低

连续ARQ协议

连续 ARQ 协议可提高信道利用率。发送方维持一个发送窗口,凡位于发送窗口内的分组可以连续发送出去,而不需要等待对方确认。接收方一般采用累计确认,对按序到达的最后一个分组发送确认,表明到这个分组为止的所有分组都已经正确收到了。

优点: 信道利用率高,容易实现,即使确认丢失,也不必重传。

缺点: 不能向发送方反映出接收方已经正确收到的所有分组的信息。 比如:发送方发送了 5条 消息,中间第三条丢失(3号),这时接收方只能对前两个发送确认。发送方无法知道后三个分组的下落,而只好把后三个全部重传一次。这也叫 Go-Back-N(回退 N),表示需要退回来重传已经发送过的 N 个消息。

滑动窗口

  • TCP 利用滑动窗口实现流量控制的机制。
  • 滑动窗口(Sliding window)是一种流量控制技术。早期的网络通信中,通信双方不会考虑网络的拥挤情况直接发送数据。由于大家不知道网络拥塞状况,同时发送数据,导致中间节点阻塞掉包,谁也发不了数据,所以就有了滑动窗口机制来解决此问题。
  • TCP 中采用滑动窗口来进行传输控制,滑动窗口的大小意味着接收方还有多大的缓冲区可以用于接收数据。发送方可以通过滑动窗口的大小来确定应该发送多少字节的数据。当滑动窗口为 0 时,发送方一般不能再发送数据报,但有两种情况除外,一种情况是可以发送紧急数据,例如,允许用户终止在远端机上的运行进程。另一种情况是发送方可以发送一个 1 字节的数据报来通知接收方重新声明它希望接收的下一字节及发送方的滑动窗口大小。

流量控制

  • TCP 利用滑动窗口实现流量控制。
  • 流量控制是为了控制发送方发送速率,保证接收方来得及接收。
  • 接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为 0,则发送方不能发送数据。

拥塞控制

在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。

为了进行拥塞控制,TCP 发送方要维持一个 拥塞窗口(cwnd) 的状态变量。拥塞控制窗口的大小取决于网络的拥塞程度,并且动态变化。发送方让自己的发送窗口取为拥塞窗口和接收方的接受窗口中较小的一个。

TCP的拥塞控制采用了四种算法,即 慢开始拥塞避免快重传快恢复。在网络层也可以使路由器采用适当的分组丢弃策略(如主动队列管理 AQM),以减少网络拥塞的发生。

  • 慢开始: 慢开始算法的思路是当主机开始发送数据时,如果立即把大量数据字节注入到网络,那么可能会引起网络阻塞,因为现在还不知道网络的符合情况。经验表明,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是由小到大逐渐增大拥塞窗口数值。cwnd初始值为1,每经过一个传播轮次,cwnd加倍。
  • 拥塞避免: 拥塞避免算法的思路是让拥塞窗口cwnd缓慢增大,即每经过一个往返时间RTT就把发送放的cwnd加1.
  • 快重传与快恢复:
    在 TCP/IP 中,快速重传和恢复(fast retransmit and recovery,FRR)是一种拥塞控制算法,它能快速恢复丢失的数据包。没有 FRR,如果数据包丢失了,TCP 将会使用定时器来要求传输暂停。在暂停的这段时间内,没有新的或复制的数据包被发送。有了 FRR,如果接收机接收到一个不按顺序的数据段,它会立即给发送机发送一个重复确认。如果发送机接收到三个重复确认,它会假定确认件指出的数据段丢失了,并立即重传这些丢失的数据段。有了 FRR,就不会因为重传时要求的暂停被耽误。  当有单独的数据包丢失时,快速重传和恢复(FRR)能最有效地工作。当有多个数据信息包在某一段很短的时间内丢失时,它则不能很有效地工作。
    快重传与快恢复

五 在浏览器中输入url地址 ->> 显示主页的过程(面试常客)

百度好像最喜欢问这个问题。

打开一个网页,整个过程会使用哪些协议

图解(图片来源:《图解HTTP》):

状态码

总体来说分为以下几个过程:

  1. DNS解析
  2. TCP连接
  3. 发送HTTP请求
  4. 服务器处理请求并返回HTTP报文
  5. 浏览器解析渲染页面
  6. 连接结束

具体可以参考下面这篇文章:

六 状态码

状态码

七 各种协议与HTTP协议之间的关系

一般面试官会通过这样的问题来考察你对计算机网络知识体系的理解。

图片来源:《图解HTTP》

各种协议与HTTP协议之间的关系

八 HTTP长连接、短连接

在HTTP/1.0中默认使用短连接。也就是说,客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web资源(如JavaScript文件、图像文件、CSS文件等),每遇到这样一个Web资源,浏览器就会重新建立一个HTTP会话。

而从HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头加入这行代码:

1
Connection:keep-alive

在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接需要客户端和服务端都支持长连接。

HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。

—— 《HTTP长连接、短连接究竟是什么?》

写在最后

计算机网络常见问题回顾

  • ①TCP三次握手和四次挥手、
  • ②在浏览器中输入url地址->>显示主页的过程
  • ③HTTP和HTTPS的区别
  • ④TCP、UDP协议的区别
  • ⑤常见的状态码。

建议

非常推荐大家看一下 《图解HTTP》 这本书,这本书页数不多,但是内容很是充实,不管是用来系统的掌握网络方面的一些知识还是说纯粹为了应付面试都有很大帮助。下面的一些文章只是参考。大二学习这门课程的时候,我们使用的教材是 《计算机网络第七版》(谢希仁编著),不推荐大家看这本教材,书非常厚而且知识偏理论,不确定大家能不能心平气和的读完。

参考

总结了部分JDK8新特性,另外一些新特性可以通过Oracle的官方文档查看,毕竟是官方文档,各种新特性都会介绍,有兴趣的可以去看。

Oracle官方文档:What’s New in JDK8



             Lambda表达式

1.什么是Lambda表达式

Lambda表达式实质上是一个可传递的代码块,Lambda又称为闭包或者匿名函数,是函数式编程语法,让方法可以像普通参数一样传递

2.Lambda表达式语法

-> {执行代码块}```
1
<br>参数列表可以为空```()->{}


可以加类型声明比如

para1, int para2) -> {return para1 + para2;}```我们可以看到,lambda同样可以有返回值.
1
<br>在编译器可以推断出类型的时候,可以将类型声明省略,比如```(para1, para2) -> {return para1 + para2;}


(lambda有点像动态类型语言语法。lambda在字节码层面是用invokedynamic实现的,而这条指令就是为了让JVM更好的支持运行在其上的动态类型语言)

3.函数式接口

在了解Lambda表达式之前,有必要先了解什么是函数式接口

1
2
3
4
5
6
7
**函数式接口指的是有且只有一个抽象(abstract)方法的接口**<br>
当需要一个函数式接口的对象时,就可以用Lambda表达式来实现,举个常用的例子:
<br>
```java
Thread thread = new Thread(() -> {
System.out.println("This is JDK8's Lambda!");
});

这段代码和函数式接口有啥关系?我们回忆一下,Thread类的构造函数里是不是有一个以Runnable接口为参数的?

1
2
3
4
5
6
7
8
9
public Thread(Runnable target) {...}

/**
* Runnable Interface
*/
@FunctionalInterface
public interface Runnable {
public abstract void run();
}

到这里大家可能已经明白了,Lambda表达式相当于一个匿名类或者说是一个匿名方法。上面Thread的例子相当于

1
2
3
4
5
6
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Anonymous class");
}
});

也就是说,上面的lambda表达式相当于实现了这个run()方法,然后当做参数传入(个人感觉可以这么理解,lambda表达式就是一个函数,只不过它的返回值、参数列表都
由编译器帮我们推断,因此可以减少很多代码量)。

Lambda也可以这样用 :

1
Runnable runnable = () -> {...};

其实这和上面的用法没有什么本质上的区别。

至此大家应该明白什么是函数式接口以及函数式接口和lambda表达式之间的关系了。在JDK8中修改了接口的规范,
目的是为了在给接口添加新的功能时保持向前兼容(个人理解),比如一个已经定义了的函数式接口,某天我们想给它添加新功能,那么就不能保持向前兼容了,
因为在旧的接口规范下,添加新功能必定会破坏这个函数式接口(JDK8中接口规范)


除了上面说的Runnable接口之外,JDK中已经存在了很多函数式接口
比如(当然不止这些):

  • 1
    - ```java.util.Comparator
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    <br>**关于JDK中的预定义的函数式接口**

    - JDK在```java.util.function```下预定义了很多函数式接口
    - ```Function<T, R> {R apply(T t);}``` 接受一个T对象,然后返回一个R对象,就像普通的函数。
    - ```Consumer<T> {void accept(T t);}``` 消费者 接受一个T对象,没有返回值。
    - ```Predicate<T> {boolean test(T t);}``` 判断,接受一个T对象,返回一个布尔值。
    - ```Supplier<T> {T get();} 提供者(工厂)``` 返回一个T对象。
    - 其他的跟上面的相似,大家可以看一下function包下的具体接口。
    ### 4.变量作用域
    ```java
    public class VaraibleHide {
    @FunctionalInterface
    interface IInner {
    void printInt(int x);
    }
    public static void main(String[] args) {
    int x = 20;
    IInner inner = new IInner() {
    int x = 10;
    @Override
    public void printInt(int x) {
    System.out.println(x);
    }
    };
    inner.printInt(30);

    inner = (s) -> {
    //Variable used in lambda expression should be final or effectively final
    //!int x = 10;
    //!x= 50; error
    System.out.print(x);
    };
    inner.printInt(30);
    }
    }
    输出 :
    30
    20

对于lambda表达式

inner
1
2
3
4
5
6
7
8
9
10
11
12
的参数列表()获取的变量成为自由变量,它是被lambda表达式捕获的。
<br>lambda表达式和内部类一样,对外部自由变量捕获时,外部自由变量必须为final或者是最终变量(effectively final)的,也就是说这个变量初始化后就不能为它赋新值,同时lambda不像内部类/匿名类,lambda表达式与外围嵌套块有着相同的作用域,因此对变量命名的有关规则对lambda同样适用。大家阅读上面的代码对这些概念应该不难理解。
<span id="MethodReferences"></span>
### 5.方法引用
**只需要提供方法的名字,具体的调用过程由Lambda和函数式接口来确定,这样的方法调用成为方法引用。**
<br>下面的例子会打印list中的每个元素:
```java
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; ++i) {
list.add(i);
}
list.forEach(System.out::println);

其中

```(para)->{System.out.println(para);}```
1
2
3
4
5
<br>我们看一下List#forEach方法 ```default void forEach(Consumer<? super T> action)```可以看到它的参数是一个Consumer接口,该接口是一个函数式接口
```java
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);

大家能发现这个函数接口的方法和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<br>我们自己定义一个方法,看看能不能像标准输出的打印函数一样被调用
```java
public class MethodReference {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; ++i) {
list.add(i);
}
list.forEach(MethodReference::myPrint);
}

static void myPrint(int i) {
System.out.print(i + ", ");
}
}

输出: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,

可以看到,我们自己定义的方法也可以当做方法引用。

到这里大家多少对方法引用有了一定的了解,我们再来说一下方法引用的形式。

  • 方法引用
    • 类名::静态方法名
    • 类名::实例方法名
    • 类名::new (构造方法引用)
    • 实例名::实例方法名
      可以看出,方法引用是通过(方法归属名)::(方法名)来调用的。通过上面的例子已经讲解了一个类名::静态方法名的使用方法了,下面再依次介绍其余的几种
      方法引用的使用方法。

类名::实例方法名

先来看一段代码

1
2
String[] strings = new String[10];
Arrays.sort(strings, String::compareToIgnoreCase);

上面的String::compareToIgnoreCase等价于(x, y) -> {return x.compareToIgnoreCase(y);}

我们看一下Arrays#sort方法public static <T> void sort(T[] a, Comparator<? super T> c),
可以看到第二个参数是一个Comparator接口,该接口也是一个函数式接口,其中的抽象方法是int compare(T o1, T o2);,再看一下
String#compareToIgnoreCase方法,public int compareToIgnoreCase(String str),这个方法好像和上面讲方法引用中类名::静态方法名不大一样啊,它
的参数列表和函数式接口的参数列表不一样啊,虽然它的返回值一样?

是的,确实不一样但是别忘了,String类的这个方法是个实例方法,而不是静态方法,也就是说,这个方法是需要有一个接收者的。所谓接收者就是
instance.method(x)中的instance,
它是某个类的实例,有的朋友可能已经明白了。上面函数式接口的compare(T o1, T o2)中的第一个参数作为了实例方法的接收者,而第二个参数作为了实例方法的
参数。我们再举一个自己实现的例子:

1
2
3
4
5
6
7
8
9
10
public class MethodReference {
static Random random = new Random(47);
public static void main(String[] args) {
MethodReference[] methodReferences = new MethodReference[10];
Arrays.sort(methodReferences, MethodReference::myCompare);
}
int myCompare(MethodReference o) {
return random.nextInt(2) - 1;
}
}

上面的例子可以在IDE里通过编译,大家有兴趣的可以模仿上面的例子自己写一个程序,打印出排序后的结果。

构造器引用

构造器引用仍然需要与特定的函数式接口配合使用,并不能像下面这样直接使用。IDE会提示String不是一个函数式接口

1
2
//compile error : String is not a functional interface
String str = String::new;

下面是一个使用构造器引用的例子,可以看出构造器引用可以和这种工厂型的函数式接口一起使用的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  interface IFunctional<T> {
T func();
}

public class ConstructorReference {

public ConstructorReference() {
}

public static void main(String[] args) {
Supplier<ConstructorReference> supplier0 = () -> new ConstructorReference();
Supplier<ConstructorReference> supplier1 = ConstructorReference::new;
IFunctional<ConstructorReference> functional = () -> new ConstructorReference();
IFunctional<ConstructorReference> functional1 = ConstructorReference::new;
}
}

下面是一个JDK官方的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static <T, SOURCE extends Collection<T>, DEST extends Collection<T>>
DEST transferElements(
SOURCE sourceCollection,
Supplier<DEST> collectionFactory) {

DEST result = collectionFactory.get();
for (T t : sourceCollection) {
result.add(t);
}
return result;
}

...

Set<Person> rosterSet = transferElements(
roster, HashSet::new);

实例::实例方法


其实开始那个例子就是一个实例::实例方法的引用

1
2
3
4
5
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; ++i) {
list.add(i);
}
list.forEach(System.out::println);

其中System.out就是一个实例,println是一个实例方法。相信不用再给大家做解释了。

总结

Lambda表达式是JDK8引入Java的函数式编程语法,使用Lambda需要直接或者间接的与函数式接口配合,在开发中使用Lambda可以减少代码量,
但是并不是说必须要使用Lambda(虽然它是一个很酷的东西)。有些情况下使用Lambda会使代码的可读性急剧下降,并且也节省不了多少代码,
所以在实际开发中还是需要仔细斟酌是否要使用Lambda。和Lambda相似的还有JDK10中加入的var类型推断,同样对于这个特性需要斟酌使用。


             JDK8接口规范

在JDK8中引入了lambda表达式,出现了函数式接口的概念,为了在扩展接口时保持向前兼容性(JDK8之前扩展接口会使得实现了该接口的类必须实现添加的方法,否则会报错。为了保持兼容性而做出妥协的特性还有泛型,泛型也是为了保持兼容性而失去了在一些别的语言泛型拥有的功能),Java接口规范发生了一些改变。

1.JDK8以前的接口规范

  • JDK8以前接口可以定义的变量和方法
    • 所有变量(Field)不论是否显式 的声明为
      static final```,它实际上都是```public static final```的。
      1
      2
      3
      4
      5
      6
         - 所有方法(Method)不论是否<i>显示</i> 的声明为```public abstract```,它实际上都是```public abstract```的。
      ```java
      public interface AInterfaceBeforeJDK8 {
      int FIELD = 0;
      void simpleMethod();
      }

以上接口信息反编译以后可以看到字节码信息里Filed是public static final的,而方法是public abstract的,即是你没有显示的去声明它。

1
2
3
4
5
6
7
8
9
10
{
public static final int FIELD;
descriptor: I
flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
ConstantValue: int 0

public abstract void simpleMethod();
descriptor: ()V
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
}

2.JDK8之后的接口规范

  • JDK8之后接口可以定义的变量和方法
    • 变量(Field)仍然必须是
      public static final```的
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
        - 方法(Method)除了可以是public abstract之外,还可以是public static或者是default(相当于仅public修饰的实例方法)的。
      从以上改变不难看出,修改接口的规范主要是为了能在扩展接口时保持向前兼容。
      <br>下面是一个JDK8之后的接口例子
      ```java
      public interface AInterfaceInJDK8 {
      int simpleFiled = 0;
      static int staticField = 1;

      public static void main(String[] args) {
      }
      static void staticMethod(){}

      default void defaultMethod(){}

      void simpleMethod() throws IOException;

      }

进行反编译(去除了一些没用信息)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
public static final int simpleFiled;
flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL

public static final int staticField;
flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL

public static void main(java.lang.String[]);
flags: (0x0009) ACC_PUBLIC, ACC_STATIC

public static void staticMethod();
flags: (0x0009) ACC_PUBLIC, ACC_STATIC

public void defaultMethod();
flags: (0x0001) ACC_PUBLIC

public abstract void simpleMethod() throws java.io.IOException;
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
Exceptions:
throws java.io.IOException
}

可以看到 default关键字修饰的方法是像实例方法(就是普通类中定义的普通方法)一样定义的,所以我们来定义一个只有default方法的接口并且实现一下这个接口试一
试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
interface Default {
default int defaultMethod() {
return 4396;
}
}

public class DefaultMethod implements Default {
public static void main(String[] args) {
DefaultMethod defaultMethod = new DefaultMethod();
System.out.println(defaultMethod.defaultMethod());
//compile error : Non-static method 'defaultMethod()' cannot be referenced from a static context
//! DefaultMethod.defaultMethod();
}
}

可以看到default方法确实像实例方法一样,必须有实例对象才能调用,并且子类在实现接口时,可以不用实现default方法,也可以选择覆盖该方法。
这有点像子类继承父类实例方法。


接口静态方法就像是类静态方法,唯一的区别是接口静态方法只能通过接口名调用,而类静态方法既可以通过类名调用也可以通过实例调用

1
2
3
4
5
6
7
8
9
interface Static {
static int staticMethod() {
return 4396;
}
}
... main(String...args)
//!compile error: Static method may be invoked on containing interface class only
//!aInstanceOfStatic.staticMethod();
...

另一个问题是多继承问题,大家知道Java中类是不支持多继承的,但是接口是多继承和多实现(implements后跟多个接口)的,
那么如果一个接口继承另一个接口,两个接口都有同名的default方法会怎么样呢?答案是会像类继承一样覆写(@Override),以下代码在IDE中可以顺利编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
interface Default {
default int defaultMethod() {
return 4396;
}
}
interface Default2 extends Default {
@Override
default int defaultMethod() {
return 9527;
}
}
public class DefaultMethod implements Default,Default2 {
public static void main(String[] args) {
DefaultMethod defaultMethod = new DefaultMethod();
System.out.println(defaultMethod.defaultMethod());
}
}

输出 : 9527

出现上面的情况时,会优先找继承树上近的方法,类似于“短路优先”。


那么如果一个类实现了两个没有继承关系的接口,且这两个接口有同名方法的话会怎么样呢?IDE会要求你重写这个冲突的方法,让你自己选择去执行哪个方法,因为IDE它还没智能到你不告诉它,它就知道你想执行哪个方法。可以通过

接口名.super```指针来访问接口中定义的实例(default)方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
```java
interface Default {
default int defaultMethod() {
return 4396;
}
}

interface Default2 {
default int defaultMethod() {
return 9527;
}
}
//如果不重写
//compile error : defaults.DefaultMethod inherits unrelated defaults for defaultMethod() from types defaults.Default and defaults.Default2
public class DefaultMethod implements Default,Default2 {
@Override
public int defaultMethod() {
System.out.println(Default.super.defaultMethod());
System.out.println(Default2.super.defaultMethod());
return 996;
}
public static void main(String[] args) {
DefaultMethod defaultMethod = new DefaultMethod();
System.out.println(defaultMethod.defaultMethod());
}
}

运行输出 :
4396
9527
996


             改进的类型推断

1.什么是类型推断

类型推断就像它的字面意思一样,编译器根据你显示声明的已知的信息 推断出你没有显示声明的类型,这就是类型推断。
看过《Java编程思想 第四版》的朋友可能还记得里面讲解泛型一章的时候,里面很多例子是下面这样的:

1
Map<String, Object> map = new Map<String, Object>();

而我们平常写的都是这样的:

1
Map<String, Object> map = new Map<>();

这就是类型推断,《Java编程思想 第四版》这本书出书的时候最新的JDK只有1.6(JDK7推出的类型推断),在Java编程思想里Bruce Eckel大叔还提到过这个问题
(可能JDK的官方人员看了Bruce Eckel大叔的Thinking in Java才加的类型推断,☺),在JDK7中推出了上面这样的类型推断,可以减少一些无用的代码。
(Java编程思想到现在还只有第四版,是不是因为Bruce Eckel大叔觉得Java新推出的语言特性“然并卵”呢?/滑稽)


在JDK7中,类型推断只有上面例子的那样的能力,即只有在使用赋值语句时才能自动推断出泛型参数信息(即<>里的信息),下面的官方文档里的例子在JDK7里会编译
错误

1
2
3
4
List<String> stringList = new ArrayList<>();
stringList.add("A");
//error : addAll(java.util.Collection<? extends java.lang.String>)in List cannot be applied to (java.util.List<java.lang.Object>)
stringList.addAll(Arrays.asList());

但是上面的代码在JDK8里可以通过,也就说,JDK8里,类型推断不仅可以用于赋值语句,而且可以根据代码中上下文里的信息推断出更多的信息,因此我们需要些的代码
会更少。加强的类型推断还有一个就是用于Lambda表达式了。


大家其实不必细究类型推断,在日常使用中IDE会自动判断,当IDE自己无法推断出足够的信息时,就需要我们额外做一下工作,比如在<>里添加更多的类型信息,
相信随着Java的进化,这些便利的功能会越来越强大。


             通过反射获得方法的参数信息

JDK8之前 .class文件是不会存储方法参数信息的,因此也就无法通过反射获取该信息(想想反射获取类信息的入口是什么?当然就是Class类了)。即是是在JDK11里
也不会默认生成这些信息,可以通过在javac加上-parameters参数来让javac生成这些信息(javac就是java编译器,可以把java文件编译成.class文件)。生成额外
的信息(运行时非必须信息)会消耗内存并且有可能公布敏感信息(某些方法参数比如password,JDK文档里这么说的),并且确实很多信息javac并不会为我们生成,比如
LocalVariableTable,javac就不会默认生成,需要你加上 -g:vars来强制让编译器生成,同样的,方法参数信息也需要加上
-parameters来让javac为你在.class文件中生成这些信息,否则运行时反射是无法获取到这些信息的。在讲解Java语言层面的方法之前,先看一下javac加上该
参数和不加生成的信息有什么区别(不感兴趣想直接看运行代码的可以跳过这段)。下面是随便写的一个类。

1
2
3
4
5
public class ByteCodeParameters {
public String simpleMethod(String canUGetMyName, Object yesICan) {
return "9527";
}
}

先来不加参数编译和反编译一下这个类javac ByteCodeParameters.java , javap -v ByteCodeParameters:

1
2
3
4
5
6
7
8
9
10
11
//只截取了部分信息
public java.lang.String simpleMethod(java.lang.String, java.lang.Object);
descriptor: (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=3, args_size=3
0: ldc #2 // String 9527
2: areturn
LineNumberTable:
line 5: 0
//这个方法的描述到这里就结束了

接下来我们加上参数javac -parameters ByteCodeParameters.java 再来看反编译的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
public java.lang.String simpleMethod(java.lang.String, java.lang.Object);
descriptor: (Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=3, args_size=3
0: ldc #2 // String 9527
2: areturn
LineNumberTable:
line 8: 0
MethodParameters:
Name Flags
canUGetMyName
yesICan

可以看到.class文件里多了一个MethodParameters信息,这就是参数的名字,可以看到默认是不保存的。

下面看一下在Intelj Idea里运行的这个例子,我们试一下通过反射获取方法名 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ByteCodeParameters {
public String simpleMethod(String canUGetMyName, Object yesICan) {
return "9527";
}

public static void main(String[] args) throws NoSuchMethodException {
Class<?> clazz = ByteCodeParameters.class;
Method simple = clazz.getDeclaredMethod("simpleMethod", String.class, Object.class);
Parameter[] parameters = simple.getParameters();
for (Parameter p : parameters) {
System.out.println(p.getName());
}
}
}
输出 :
arg0
arg1

???说好的方法名呢????别急,哈哈。前面说了,默认是不生成参数名信息的,因此我们需要做一些配置,我们找到IDEA的settings里的Java Compiler选项,在
Additional command line parameters:一行加上-parameters(Eclipse 也是找到Java Compiler选中Stoer information about method parameters),或者自
己编译一个.class文件放在IDEA的out下,然后再来运行 :

1
2
3
输出 :
canUGetMyName
yesICan

这样我们就通过反射获取到参数信息了。想要了解更多的同学可以自己研究一下 [官方文档]
(https://docs.oracle.com/javase/tutorial/reflect/member/methodparameterreflection.html)

总结与补充

在JDK8之后,可以通过-parameters参数来让编译器生成参数信息然后在运行时通过反射获取方法参数信息,其实在SpringFramework
里面也有一个LocalVariableTableParameterNameDiscoverer对象可以获取方法参数名信息,有兴趣的同学可以自行百度(这个类在打印日志时可能会比较有用吧,个人感觉)。