1
2
3

传递信息:

在进行收发数据操作
之前,双方需要先建立起这条管道才行。建立管道的关键在于管道两端的
数据出入口,这些出入口称为套接字。我们需要先创建套接字,然后再将
套接字连接起来形成管道。实际的过程是下面这样的。首先,服务器一方
先创建套接字,然后等待客户端向该套接字连接管道 A。当服务器进入等待
状态时,客户端就可以连接管道了。具体来说,客户端也会先创建一个套
接字,然后从该套接字延伸出管道,最后管道连接到服务器端的套接字上。
当双方的套接字连接起来之后,通信准备就完成了。接下来,就像我们刚
刚讲过的一样,只要将数据送入套接字就可以收发数据了。
我们再来看一看收发数据操作结束时的情形。当数据全部发送完毕之
后,连接的管道将会被断开。管道在连接时是由客户端发起的,但在断开
时可以由客户端或服务器任意一方发起 A。其中一方断开后,另一方也会随之
断开,当管道断开后,套接字也会被删除。到此为止,通信操作就结束了。
综上所述,收发数据的操作分为若干个阶段,可以大致总结为以下 4 个。
(1)创建套接字(创建套接字阶段)
(2)将管道连接到服务器端的套接字上(连接阶段)
(3)收发数据(通信阶段)
(4)断开管道并删除套接字(断开阶段)

套间字是电话机,端口区分每个的电话机, 在同一个地址多个电话机和多个电话机回复的时候,能确定本地哪个电话接受远程哪个电话机的信息,从而建立好稳定的连接。
而这些是比较底层的,是浏览器一路请求下来,调用socket函数,直到调用操作系统的协议栈,才做到的。同时传播时候遵守http,tcp/ip,还有三次握手的协议,要靠DNS解析。

套接字中必须要记录是否已经收到响应,以及发送数据后经过了多长时间,才能根据这些信息按照需要执行重发操作。
协议栈是根据套接字中记录的控制信息来工作的。
4

5DNS 查名字,ARP 查门牌,MAC 真收件。

协议栈

在协议栈内部有一块用于存放控制信息的内存空间,这里记录了用于
控制通信操作的控制信息,例如通信对象的 IP 地址、端口号、通信操作的
进行状态等。本来套接字就只是一个概念而已,并不存在实体,如果一定
要赋予它一个实体,我们可以说这些控制信息就是套接字的实体,或者说
存放控制信息的内存空间就是套接字的实体

通信操作中使用的控制信息分为两类。
(1)头部中记录的信息
(2)套接字(协议栈中的内存空间)中记录的信息

tcp传播

当 TCP 头部创建好之后,接下来 TCP 模块会将信息传递给 IP 模块并
委托它进行发送 A。IP 模块执行网络包发送操作后,网络包就会通过网络到
达服务器,然后服务器上的 IP 模块会将接收到的数据传递给 TCP 模块,
服务器的 TCP 模块根据 TCP 头部中的信息找到端口号对应的套接字,也
就是说,从处于等待连接状态的套接字中找到与 TCP 头部中记录的端口号
相同的套接字就可以了。当找到对应的套接字之后,套接字中会写入相应
的信息,并将状态改为正在连接 B。上述操作完成后,服务器的 TCP 模块会
返回响应,这个过程和客户端一样,需要在 TCP 头部中设置发送方和接收
方端口号以及 SYN 比特 C。此外,在返回响应时还需要将 ACK 控制位设为
1D,这表示已经接收到相应的网络包。网络中经常会发生错误,网络包也会
发生丢失,因此双方在通信时必须相互确认网络包是否已经送达 E,而设置
ACK 比特就是用来进行这一确认的。接下来,服务器 TCP 模块会将 TCP
头部传递给 IP 模块,并委托 IP 模块向客户端返回响应。
然后,网络包就会返回到客户端,通过 IP 模块到达 TCP 模块,并通
过 TCP 头部的信息确认连接服务器的操作是否成功。如果 SYN 为 1 则表
2.3 收发数据
示连接成功,这时会向套接字中写入服务器的 IP 地址、端口号等信息,同
时还会将状态改为连接完毕。到这里,客户端的操作就已经完成,但其实还
剩下最后一个步骤。刚才服务器返回响应时将 ACK 比特设置为 1,相应地,
客户端也需要将 ACK 比特设置为 1 并发回服务器,告诉服务器刚才的响应
包已经收到。当这个服务器收到这个返回包之后,连接操作才算全部完成。
现在,套接字就已经进入随时可以收发数据的状态了,大家可以认为
这时有一根管子把两个套接字连接了起来。当然,实际上并不存在这么一
根管子,不过这样想比较容易理解,网络业界也习惯这样来描述。这根管
子,我们称之为连接 A。只要数据传输过程在持续,也就是在调用 close 断
开之前,连接是一直存在的

ACK号

6
TCP 采用这样的方式确认对方是否收到了数据,在得到对方确认之
前,发送过的包都会保存在发送缓冲区中。如果对方没有返回某些包对应
的 ACK 号,那么就重新发送这些包。
可能会发生已经重传了包之后,
前面的 ACK 号才姗姗来迟的情况。这样的重传是多余的,看上去只是多
发一个包而已,但它造成的后果却没那么简单 A。因为 ACK 号的返回变慢
大多是由于网络拥塞引起的,因此如果此时再出现很多多余的重传,对于
本来就很拥塞的网络来说无疑是雪上加霜
TCP 采用了动态调整等待时间的方法,这个等待时间是
根据 ACK 号返回所需的时间来判断的。具体来说,TCP 会在发送数据
的过程中持续测量 ACK 号的返回时间,如果 ACK 号返回变慢,则相应
延长等待时间;相对地,如果 ACK 号马上就能返回,则相应缩短等待
时间

滑动 窗口

随着数据收发的进行,数据不断传递给应用程序,
接收缓冲区就会被逐步释放。这时,服务器需要将新的窗口大小告知客户
端。当服务器收到客户端的请求消息后,会向客户端返回响应消息

tcp断开

协议栈在设计上允许任何一方先发起断开过程
这里我们以服
务器一方发起断开过程为例来进行讲解。首先,服务器一方的应用程序会
调用 Socket 库的 close 程序。然后,服务器的协议栈会生成包含断开信息
的 TCP 头部,具体来说就是将控制位中的 FIN 比特设为 1。接下来,协议
栈会委托 IP 模块向客户端发送数据(图 2.12 ①)。同时,服务器的套接字
中也会记录下断开操作的相关信息。
接下来轮到客户端了。当收到服务器发来的 FIN 为 1 的 TCP 头部时,
客户端的协议栈会将自己的套接字标记为进入断开操作状态。然后,为
了告知服务器已收到 FIN 为 1 的包,客户端会向服务器返回一个 ACK 号
(图 2.12 ②)。这些操作完成后,协议栈就可以等待应用程序来取数据了。
过了一会儿,应用程序就会调用 read 来读取数据 A。这时,协议栈不会
向应用程序传递数据 A,而是会告知应用程序(浏览器)来自服务器的数据
已经全部收到了。根据规则,服务器返回请求之后,Web 通信操作就全部
结束了,因此只要收到服务器返回的所有数据,客户端的操作也就随之结
束了。因此,客户端应用程序会调用 close 来结束数据收发操作,这时客
户端的协议栈也会和服务器一样,生成一个 FIN 比特为 1 的 TCP 包,然后
委托 IP 模块发送给服务器(图 2.12 ③)。一段时间之后,服务器就会返回
ACK 号(图 2.12 ④)。到这里,客户端和服务器的通信就全部结束了。
等待几分钟之后再删除套接字

ip

7
(1)路由器根据目标地址判断下一个路由器的位置
(2)集线器在子网中将网络包传输到下一个路由
实际上,集线器是按照以太网规则传输包的设备,而路由器是按照 IP
规则传输包的设备,因此我们也可以作如下理解。
(1)IP 协议根据目标地址判断下一个 IP 转发设备的位置
(2)子网中的以太网协议将包传输到下一个转发设备

服务器

防火墙

8
防火墙为什么要看 TCP 控制位?
安全性:
防止内网主机发起非法连接(如被木马控制主动连接外部)
拦截 SYN 洪水攻击(大量 SYN=1 的连接尝试)
连接状态管理(状态检测防火墙)
判断一个包是否是“新连接”、“已建立连接”、“无效连接”
有状态防火墙(stateful firewall)就靠这个来“智能放行”

互联网应用

信息头

cookie可以把用户访问一个网站的所有数据储存下来,由js生成。比如当我们首次登录B站时,服务器会创建一些信息并发送给浏览器,浏览器会对这些信息进行保存(按域名划分)。当我们后续访问该域名时,浏览器会自动把该域名下的信息与http请求一同发送给网站服务器,这样B站就知道我们已经登录过了。
浏览器以 domain+path 来设置 cookie 的作用范围
last-modified做一个本地缓存的判断,如果本地缓存过期了就重新存

响应头

f12

可以直接在样式表里调试
可以在调试器js文件里做断点调试。

js

解释性语言的热修复js,lua,python
js的安全沙箱