参考引用
1. 网络通信概述
- 网络通信本质上是一种进程间通信,是位于网络中不同主机上的进程之间的通信,属于 IPC 的一种,通常称为 socket IPC,网络通信是为了解决在网络环境中,不同主机上的应用程序之间的通信问题
- 网络通信可以分为三个层次
- 硬件层:网卡设备,收发网络数据
- 驱动层:网卡驱动(Linux 内核网卡驱动代码)
- 应用层:上层应用程序(调用 socket 接口或更高级别接口实现网络相关应用程序)
1.1 硬件层
- 网卡设备是实现网络数据收发的硬件基础
- 并且通信的两台主机之间需要建立网络连接,这样两台主机之间才可以进行数据传输,如通过网线进行数据传输
- 网络数据的传输媒介有很多种
- 大体上分为有线传输(如双绞线网线、光纤等),PC 机通常使用有线网络
- 无线传输(如 WIFI、蓝牙、ZigBee、4G/5G/GPRS 等),手机等移动设备通常使用无线网络
1.2 内核层
- 提供了网卡驱动程序,可以驱动底层网卡硬件设备,同时向应用层提供 socket 接口
1.3 应用层
- 应用程序基于内核提供的 socket 接口进行应用编程,实现自己的网络应用程序
- socket 接口是内核向应用层提供的一套网络编程接口,学习网络编程就是学习如何基于 socket 接口编写应用程序
- 除了 socket 接口之外,在应用层通常还会使用一些更为高级的编程接口,如 http、网络控件等,这些接口实际上是对 socket 接口的一种更高级别的封装
2. 网络互连模型:OSI 七层模型
- OSI(Open System Interconnection)七层参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间网络互联的标准体系,一般称为 OSI 参考模型或七层模型,OSI 七层模型是一个网络互连模型
2.1 物理层
- 物理层(Physical Layer)是 OSI 参考模型的最底层
- 主要功能
- 利用传输介质为数据链路层提供物理连接
- 实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异,使数据链路层不必考虑网络的具体传输介质是什么
- 网络数据信号的传输是通过物理层实现,通过物理介质传输比特流
- 物理层规定了物理设备标准、电平、传输速率等
- 常用物理层传输介质:集线器、中继器、调制解调器、网线、双绞线、同轴电缆等
- 主要功能
2.2 数据链路层
- 数据链路层(Data Link Layer)是 OSI 参考模型中的第二层
- 主要功能
- 建立和管理节点间逻辑连接(将原始比特流转变为逻辑传输)、硬件地址寻址、差错检测等功能
- 将比特组合成字节进而组合成帧,用 MAC 地址访问介质,错误发现但不能纠正
- 具体工作
- 接收来自物理层的位流形式的数据,并封装成帧,传送到上一层
- 同样,也将来自上层的数据帧,拆装为位流形式的数据转发到物理层
- 并且,还负责处理接收端发回的确认帧的信息,以便提供可靠的数据传输
- 数据链路层又分为 2 个子层:逻辑链路控制子层(LLC)和媒体访问控制子层(MAC)
- MAC 子层:解决共享型网络中多用户对信道竞争的问题,完成网络介质的访问控制
- LLC 子层:建立和维护网络连接,执行差错校验、流量控制和链路控制
- 主要功能
2.3 网络层
- 网络层(Network Layer)是 OSI 参考模型中的第三层,也就是通常说的 IP 层
- 主要功能
- 进行逻辑地址寻址,实现不同网络之间的路径选择
- 通过 IP 寻址来建立两个节点之间的连接,为源端发送的数据包选择合适的路由和交换节点,正确无误地按照地址传送给目的端的运输层
- 该层包含的协议有
- IP(Ipv4、Ipv6)、ICMP、IGMP 等
- 主要功能
2.4 传输层
- 传输层(Transport Layer)是 OSI 参考模型中的第四层,通常说的 TCP、UDP 协议就工作在这一层
- 主要功能
- 定义传输数据的协议端口号,以及端到端的流控和差错校验
- 建立主机端到端的连接,为上层协议提供端到端的可靠和透明的数据传输服务
- 主要功能
2.5 会话层
- 会话层(Session Layer)是 OSI 参考模型中的第五层
- 主要功能
- 建立、管理和终止表示层实体之间的通信会话
- 组织和协调两个会话进程之间的通信,并对数据交换进行管理
- 该层的通信由不同设备中的应用程序之间的服务请求和响应组成,将不同实体之间表示层的连接称为会话
- 对应主机进程,指本地主机与远程主机正在进行的会话
- 主要功能
2.6 表示层
- 表示层(Presentation Layer)是 OSI 参考模型中的第六层
- 主要功能
- 提供用于应用层数据的编码和转换功能,确保一个系统应用层发送的数据能被另一个系统应用层识别
- 提供一种标准表示形式,用于将计算机内部的多种数据格式转换成通信中采用的标准表示形式
- 数据压缩/解压缩和加密/解密(提供网络的安全性)
- 主要功能
2.7 应用层
- 应用层(Application Layer)是 OSI 参考模型中的最高层,是最靠近用户的一层
- 主要功能
- 为上层用户提供应用接口,也为用户直接提供各种网络服务
- 常见应用层的网络服务协议
- HTTP、FTP、TFTP、SMTP、SNMP、DNS、TELNET、HTTPS、POP3、DHCP
- 主要功能
3. TCP/IP 四层/五层模型
- TCP/IP 模型是 OSI 模型的简化版本
- TCP/IP 五层模型将 OSI 七层模型的最上三层(应用层、表示层和会话层)合并为应用层
- TCP/IP 四层模型与五层模型唯一不同的就是将数据链路层和物理层合并为网络接口层
实际的应用中更多还是使用 TCP/IP 四层模型
4. 数据的封装与拆封
- 网络通信中,数据从上层到下层交付时,要进行封装;同理,当目标主机接收到数据时,数据由下层传递给上层时需要进行拆封,将每一层的首部进行拆解最终得到用户数据,这就是数据的封装与拆封
- 数据的封装过程如下图所示
- 当用户发送数据时,将数据向下交给传输层,但是在交给传输层之前,应用层相关协议会对用户数据进行封装,如 MQTT、HTTP 等协议,其实就是在用户数据前添加一个应用程序头部
- 传输层会在数据前面加上传输层首部(此处以 TCP 协议为例,图中的传输层首部为 TCP 首部,也可以是 UDP 首部),然后向下交给网络层
- 网络层会在数据前面加上网络层首部(IP 首部),然后将数据向下交给链路层,链路层会对数据进行最后一次封装,即在数据前面加上链路层首部(此处使用以太网接口为例,对应以太网首部),然后将数据交给网卡
- 最后,由网卡硬件设备将数据转换成物理链路上的电平信号,数据就这样被发送到了网络中
5. IP 地址
- Internet 依靠 TCP/IP 协议,在全球范围内实现不同硬件结构、不同操作系统、不同网络系统的主机之间互联
- 在 Internet 上,每一个节点都依靠唯一的 IP 地址相互区分和相互联系,IP 地址用于标识互联网中每台主机的身份
- 设计人员为每个接入网络中的主机都分配一个 IP 地址(Internet Protocol Address),只有合法的 IP 地址才能接入互联网中并且与其他主机进行网络通信
- IP 地址是软件地址,不是硬件地址,硬件 MAC 地址是存储在网卡中的,应用于局域网中寻找目标主机
5.1 IP 地址的编址方式
- 传统的 IP 地址是一个 32 位二进制数的地址,也叫 IPv4 地址,由 4 个 8 位字段组成。除了 IPv4 之外,还有 IPv6,IPv6 采用 128 位地址长度,8 个 16 位字段组成
- 在网络通信数据包中,IP 地址以 32 位(4 个 8 位字段)二进制的形式表示
- IP 地址中的 32 位实际上包含 2 部分,分别为网络地址和主机地址,可通过子网掩码来确定网络地址和主机地址分别占用多少位
- 在人机交互中,通常使用点分十进制方式表示,如 192.168.1.1
- 在网络通信数据包中,IP 地址以 32 位(4 个 8 位字段)二进制的形式表示
5.2 IP 地址分类
- 根据 IP 地址中网络地址和主机地址分别占多少位,将 IP 地址划分为 5 类,分别为 A、B、C、D、E 五类
5.2.1 A 类 IP 地址
- 一个 A 类 IP 地址由 1 个字节网络地址和 3 个字节主机地址组成,网络地址的最高位必须为 0
- 因此可知,网络地址取值范围为 0~127(2^7 个),一共 128 个网络地址
- 这 128 个网络地址中,其中 3 个网络地址用作特殊用途,因此可用的网络地址有 125 个
- A 类地址范围为:1.0.0.1 ~ 127.255.255.254
- A 类地址中设有私有地址和保留地址
- 10.X.X.X 是私有地址,只能用于局域网中的地址
- 127.X.X.X 是保留地址,用作循环测试使用
- 默认网络掩码为:255.0.0.0
- A 类地址分配给具有大量主机而局域网络个数较少的大型网络,如 IBM 公司的网络
5.2.1 B 类 IP 地址
- 一个 B 类 IP 地址由 2 个字节的网络地址和 2 个字节的主机地址组成,网络地址的最高位必须是 “10”
- 因此,网络地址第一个字节的取值范围为 128~191(2^6 个),IP 地址范围从 128.0.0.0 到 191.255.255.255
- B 类地址范围:128.0.0.1 ~ 191.255.255.254
- 对于 B 类地址来说,一共拥有 16384 个网络地址,其中可用的网络地址有 16382 个,每个网络地址能容纳约 6 万(2^16-2=65534)多个主机
- B 类地址中设有私有地址和保留地址
- 172.16.0.0 ~ 172.31.255.255 是私有地址
- 169.254.X.X 是保留地址。如果你的 IP 地址是自动获取 IP 地址,而你在网络上又没有找到可用的 DHCP 服务器,就会得到其中一个 IP
- 默认网络掩码为:255.255.0.0
- B 类地址分配给一般的中型网络
5.2.1 C 类 IP 地址
- 个 C 类 IP 地址由 3 字节的网络地址和 1 字节的主机地址组成,网络地址的最高位必须是 “110”
- 因此 C 类 IP 地址的第一个字节的取值范围为 192~223(2^5 个),范围从 192.0.0.0 到 223.255.255.255
- C 类地址范围为:192.0.0.1 ~ 223.255.255.254
- 网络地址可达 209 万余个,每个网络地址能容纳 254 个主机
- C 类地址中的私有地址:192.168.X.X 是私有地址
- 默认网络掩码为:255.255.255.0
- C 类地址分配给小型网络,如一般的局域网和校园网,它可连接的主机数量是最少的,采用把所属的用户分为若干的网段进行管理
5.2.1 D 类 IP 地址
- D 类 IP 地址第一个字节以 “1110” 开始,它是一个专门保留的地址,它并不指向特定的网络
- 目前这一类地址被用在多点广播(多播,Multicast),多点广播地址用来一次寻址一组计算机,它标识共享同一协议的一组计算机
- D 类地址不分网络地址和主机地址,它的第 1 个字节的高四位固定为 1110
- D 类地址范围:224.0.0.1 ~ 239.255.255.254
5.2.1 E 类 IP 地址
- E 类 IP 地址以 “llll0” 开始,为将来使用保留
- 全零(“0.0.0.0”)地址对应于当前主机
- 全 “1” 的 IP 地址 (“255.255.255.255”) 是当前子网的广播地址
- E 类地址也不分网络地址和主机地址,它的第 1 个字节的前五位固定为 11110。
- E 类地址范围:240.0.0.1 ~ 255.255.255.254
5.3 特殊的 IP 地址
下面是一些特殊的 IP 地址,不能分配给任何一个网络的主机使用
-
直接广播地址
- 向某个网络上所有的主机发送报文,TCP/IP 规定,主机号各位全部为 “1” 的 IP 地址用于广播,叫作广播地址
- 如:一个 IP 地址是 192.168.0.181,这是一个 C 类地址,所以它的主机号只有一个字节,那么对主机号全取 1 得到一个广播地址 192.168.0.255,向这个地址发送数据就能让同一网络下的所有主机接收到
- A 类地址的广播地址为:XXX.255.255.255(XXX 为 A 类地址中网络地址的取值范围,如:120.255.255.255)
- B 类地址的广播地址为:XXX.XXX.255.255(XXX 为 B 类地址中网络地址的取值范围,如:139.22.255.255)
- C 类地址的广播地址为:XXX.XXX.XXX.255(XXX 为 C 类地址中网络地址的取值范围,如:203.120.16.255)
-
受限广播地址
- 直接广播要求发送方必须广播网络对应的网络号。但有些主机在启动时,往往并不知道本网络的网络号,这时候如果想要向本网络广播,只能采用受限广播地址(Limited Broadcast Address)
- 受限广播地址是在本网络内部进行广播的一种广播地址,TCP/IP 规定,32 比特全为 “1” 的 IP 地址用于本网络内的广播,也就是 255.255.255.255
-
多播地址
- 多播地址用在一对多的通信中,即一个发送者,多个接收者,不论接受者数量的多少,发送者只发送一次数据包
- 多播地址属于 D 类地址,D 类地址只能用作目的地址,而不能作为主机中的源地址
-
环回地址
- 环回地址(Loopback Address)是用于网络软件测试以及本机进程之间通信的特殊地址
- 把 A 类地址中的 127.XXX.XXX.XXX 的所有地址都称为环回地址,主要用来测试网络协议是否工作正常的作用,比如在电脑中使用 ping 命令去 ping 127.1.1.1 就可以测试本地 TCP/IP 协议是否正常
- 不能将环回地址作为任何一台主机的 IP 地址使用
-
0.0.0.0 地址
- IP 地址 32bit 全为 0 的地址(也就是 0.0.0.0)表示本网络上的本主机,只能用作源地址
- 0.0.0.0 不能被 ping 通,在服务器中,0.0.0.0 并不是一个真实的的 IP 地址,它表示本机中所有的 IPv4 地址
- 监听 0.0.0.0 的端口,就是监听本机中所有 IP 的端口
如何判断 2 个 IP 地址是否在同一个网段内?
- 可通过网络标识来进行判断,网络标识定义:网络标识 = IP 地址 & 子网掩码
- 2 个 IP 地址的网络标识相同,那么它们就处于同一网络。譬如 192.168.1.50 和 192.168.1.100,这 2 个都是 C 类地址,对应的子网掩码为 255.255.255.0,很明显,这两个 IP 地址与子网掩码进行按位与操作时得到的结果(网络标识)是一样的,所以它们处于同一网络
6. TCP/IP 协议
- TCP/IP 协议它其实是一个协议族,包含了众多的协议,如应用层协议 HTTP、FTP、MQTT 以及传输层协议 TCP、UDP 等这些都属于 TCP/IP 协议
6.1 HTTP 协议
- HTTP 超文本传输协议(HyperText Transfer Protocol,HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议
- HTTP 是万维网数据通信的基础
- HTTP 的应用最为广泛,如:经常会打开网页浏览器查询资料,通过浏览器便可开启 HTTP 通信
- HTTP 协议工作于客户端(用户)、服务器端(网站)模式下
- 浏览器作为 HTTP 客户端通过 URL 向 HTTP 服务端即 Web 服务器发送请求
- Web 服务器根据接收到的请求后,向客户端发送响应信息
6.2 FTP 协议
- FTP 协议的英文全称为 File Transfer Protocol,简称为 FTP,它是一种文件传输协议,从一个主机向一个主机传输文件的协议
- FTP 协议同样也是基于客户端-服务器模式,在客户端和服务器之间进行文件传输,通常会使用 FTP 协议在两台主机之间进行文件传输
- 如:一台 Ubuntu 系统主机和一台 Windows 系统主机,将一台主机作为 FTP 服务器,另一台主机作为 FTP 客户端,建立 FTP 连接之后,客户端可以从服务器下载文件,同样也可以将文件上传至服务器
- FTP 除了基本的文件上传/下载功能外,还有目录操作、权限设置、身份验证等机制,许多网盘的文件传输功能都是基于 FTP 实现的
7. TCP 协议
-
TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于 IP 的传输协议
- TCP 协议工作在传输层,对上服务 socket 接口,对下调用 IP 层(网络层)
- TCP 是一种面向连接的传输协议,通信之前必须通过三次握手与客户端建立连接关系后才可通信
- TCP 协议提供可靠传输,不怕丢包、乱序
-
TCP 协议如何保证可靠传输?
- TCP 协议采用发送应答机制,即发送端发送的每个 TCP 报文段都必须得到接收方的应答,才能认为这个 TCP 报文段传输成功
- TCP 协议采用超时重传机制,发送端在发送出一个 TCP 报文段之后启动定时器,如果在定时时间内未收到应答,它将重新发送该报文段
- 由于 TCP 报文段最终是以 IP 数据报发送的,而 IP 数据报到达接收端可能乱序、重复,所以 TCP 协议还会将接收到的 TCP 报文段重排、整理,再交付给应用层
7.1 TCP 协议的特性
-
1. 面向连接的
- TCP 是一个面向连接的协议,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一个 TCP 连接,否则将无法发送数据,通过三次握手建立连接
-
2. 确认与重传
- 当数据从主机 A 发送到主机 B 时,主机 B 会返回给主机 A 一个确认应答,TCP 通过确认应答 ACK 实现可靠的数据传输
- 当发送端将数据发送出去之后会等待对端的确认应答。如果有确认应答,说明数据已经成功到达对端。反之,数据丢失的可能性比较大
- 在一定的时间内如果没有收到确认应答,发送端就可以认为数据已经丢失,并进行重发。由此,即使产生了丢失,仍然可以保证数据能够到达对端,实现可靠传输
-
3. 全双工通信
- TCP 连接一旦建立,就可以在连接上进行双向的通信。任何一个主机都可以向另一个主机发送数据,数据是双向流通的,所以 TCP 协议是一个全双工的协议
-
4. 基于字节流而非报文
- 将数据按字节大小进行编号,接收端通过 ACK 来确认收到的数据编号,通过这种机制能够保证 TCP 协议的有序性和完整性,因此 TCP 能够提供可靠性传输
-
5. 流量控制(滑动窗口协议)
- 针对接收端的处理速度不如发送端发送速度快的问题,消除发送方使接收方缓存溢出的可能性
- TCP 流量控制主要使用滑动窗口协议
- 滑动窗口是接收端使用的窗口大小,用来告诉发送端接收端的缓存大小,以此可以控制发送端发送数据的大小,从而达到流量控制的目的,这个窗口大小就是一次传输几个数据
- 对所有数据帧按顺序赋予编号,发送端在发送过程中始终保持一个发送窗口,只有落在发送窗口内的帧才允许被发送,同时接收端也维持一个接收窗口,只有落在接收窗口内的帧才允许接收,这样通过调整发送方窗口和接收方窗口的大小可以实现流量控制
-
6. 差错控制
- 除了确认应答与重传机制外,TCP 协议也会采用校验和的方式来检验数据的有效性,主机在接收数据的时候,会将重复的报文丢弃,将乱序的报文重组,发现某段报文丢失了会请求发送方进行重发,因此在 TCP 往上层协议递交的数据是顺序的、无差错的完整数据
-
7. 拥塞控制
- 如果网络上的负载(发送到网络上的分组数)大于网络上的容量(网络同时能处理的分组数),就可能引起拥塞
- 判断网络拥塞的两个因素
- 延时和吞吐量
- 拥塞控制机制是
- 开环(预防)和闭环(消除)
- TCP 拥塞控制的几种方法
- 慢启动:在开始发送数据时,TCP 发送方将发送窗口从一个 MSS(最大报文段长度)开始,每当收到一个确认后,它将窗口大小加倍,以此达到稳定的发送速率,直到达到拥塞避免阈值
- 拥塞避免:一旦达到拥塞避免阈值,在 TCP 发送方继续对网络进行压力测试之前,它会缓慢地增加发送窗口。如果在网络中没有出现拥塞,则发送窗口会不断增加,直到达到硬性限制
- 快重传:快重传指在发送端连续收到三个相同的 ACK 时,即会立即重发未被确认的数据,而不等待超时
- 快恢复:当接收方收到重复 ACK 时,它会通知发送方进行快速重传。在快速重传期间,发送方将窗口减半,然后尝试重新发送未被确认的报文段,以便更快地恢复该连接的正常状态
流量控制是通过接收端来控制流量的一种方式,而拥塞控制则是通过发送端来控制流量的一种方式。TCP 发送端可能因为 IP 网络的拥塞而被遏制,TCP 拥塞控制就是为了解决这个问题
7.2 TCP 报文格式
TCP 报文由 TCP 首部 + 数据区域组成,一般 TCP 首部通常为 20 个字节大小,具体格式如下图
-
1. 源端口号和目标端口号
- 源端口号和目标端口号各占 2 个字节,一个 4 个字节,每个 TCP 报文都包含源主机和目标主机的端口号,用于寻找发送端和接收端应用进程,这两个值加上 IP 首部中的源 IP 地址和目标 IP 地址就能确定唯一的 TCP 连接
- 有时一个 IP 地址和一个端口号也称为 socket(插口)
-
2. 序号 seq
- 占 4 个字节,用来标识从 TCP 发送端向 TCP 接收端发送的数据字节流,它的值表示在这个报文段中的第一个数据字节所处位置码,根据接收到的数据区域长度,就能计算出报文最后一个数据所处的序号,因为 TCP 协议会对发送或者接收的数据进行编号(按字节的形式),那么使用序号对每个字节进行计数,就能很轻易管理这些数据
- 在 TCP 传送的数据流中,每一个字节都有一个序号。例如,一报文段的序号为 300,而且数据共 100 字节,则下一个报文段的序号就是 400;序号是 32bit 的无符号数,序号到达 2^32-1 后从 0 开始
-
3. 确认序号 ack
- 确认序号占 4 字节,是期望收到对方下次发送的数据的第一个字节的序号,也就是期望收到的下一个报文段的首部中的序号,确认序号应该是上次已成功收到数据字节序号 +1
- 只有 ACK 标志为 1 时,确认序号才有效
- TCP 为应用层提供全双工服务,这意味数据能在两个方向上独立地进行传输,因此确认序号通常会与反向数据(即接收端传输给发送端的数据)封装在同一个报文中,所以连接的每一端都必须保持每个方向上的传输数据序号准确性
-
4. 首部长度
- 首部长度字段占 4 个 bit 位,它指出了 TCP 报文段首部长度,以字节为单位,最大能记录 15*4=60 字节的首部长度,因此,TCP 报文段首部最大长度为 60 字节
- 在字段后接下来有 6bit 空间是保留未用的,供以后应用,现在置为 0
-
5. 六个标志位:URG/ACK/PSH/RST/SYN/FIN
- URG:首部中的紧急指针字段标志,如果是 1 表示紧急指针字段有效
- ACK:用于应答,只有当 ACK=1 时,确认序号 ack 字段才有效
- PSH:当 PSH=1 时,接收方应该尽快将本报文段立即传送给其应用层
- RST:当 RST=1 时,表示出现连接错误,必须释放连接,然后再重建传输连接。复位比特还用来拒绝一个不法的报文段或拒绝打开一个连接
- SYN:SYN=1,ACK=0 时表示请求建立一个连接,携带 SYN 标志的 TCP 报文段为同步报文段
- FIN:FIN=1 表示发送方没有数据要传输了,要求释放连接
-
6. 窗口大小
- 占用 2 个字节大小,表示从确认序号开始,本报文的发送方可以接收的字节数,即接收窗口大小,用于流量控制
-
7. 校验和
- 对整个的 TCP 报文段(包括 TCP 首部和 TCP 数据),以 16 位制进行计算所得
- 这是一个强制性的字段
-
8. 紧急指针
- 本报文段中的紧急数据的最后一个字节的序号
-
9. 选项
- 选项字段的大小是不确定的,最多 40 字节
7.3 建立 TCP 连接:三次握手
- TCP 是一个面向连接的协议,双方在进行网络通信之前,必须先在双方之间建立一条连接,俗称 “握手”
- “三次握手” 是指建立 TCP 连接的过程,通信双方建立一个 TCP 连接需要经过 “三次握手” 这样一个过程
- 建立连接的过程是由客户端发起,而服务器会时刻监听、等待着客户端的连接
- 三次握手过程发生在内核空间,体现在用户空间上的是:accept() 和 connect() 成功执行并返回了
7.3.1 三次握手的过程
- 第一次握手
- 客户端将 TCP 报文标志位 SYN 置为 1,随机产生一个序号值 seq=J,保存在 TCP 首部的序列号(Sequence Number)字段里,指明客户端打算连接的服务器的端口,并将该数据包发送给服务器端,发送完毕后,客户端进入 SYN_SENT 状态,等待服务器端确认
- 第二次握手
- 服务器端收到数据包后由标志位 SYN=1 知道客户端请求建立连接,服务器端将 TCP 报文标志位 SYN 和 ACK 都置为 1,ack=J+1,随机产生一个序号值 seq=K,并将该数据包发送给客户端以确认连接请求,服务器端进入 SYN_RCVD 状态
小写的 ack 代表的是头部的确认号 Acknowledge number,ack。大写的 ACK,则是 TCP 首部的标志位,用于标志的 TCP 包是否对上一个包进行了确认操作,如果确认了,则把 ACK 标志位设置成 1
- 第三次握手
- 客户端收到确认后,检查 ack 是否为 J+1,ACK 是否为 1,如果正确则将标志位 ACK 置为 1,ack=K+1,并将该数据包发送给服务器端,服务器端检查 ack 是否为 K+1,ACK 是否为 1,如果正确则连接建立成功,客户端和服务器端进入 ESTABLISHED 状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了
在完成握手后,客户端与服务器就成功建立了连接,同时双方都得到了彼此的窗口大小、序列号等信息,在传输 TCP 报文段的时候,每个 TCP 报文段首部的 SYN 标志都会被置 0,因为它只用于发起连接、同步序号
7.3.2 为什么需要三次握手?
- 其实 TCP 三次握手过程跟现实生活中的人与人之间的电话交流是很类似的,A 打电话给 B
- A:“喂,你能听到我的声音吗?”
- B:“我听得到呀,你能听到我的声音吗?”
- A:“我能听到你,………”
- …
- 经过三次的互相确认,大家就会认为对方对听的到自己说话,才开始接下来的沟通交流,否则,如果不进行确认,那么你在说话的时候,对方不一定能听到你的声音。所以,TCP 的三次握手是为了保证传输的安全、可靠
7.4 关闭 TCP 连接:四次挥手
- 四次挥手即终止 TCP 连接,就是指断开一个 TCP 连接时,需要客户端和服务端总共发送 4 个包以确认连接的断开,在 socket 编程中,这一过程由客户端或服务端任一方执行 close 来触发
- 由于 TCP 连接是全双工的,因此每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个 FIN 来终止这一方向的连接,收到一个 FIN 只是意味着这一方向上不会再收到数据了,但是在这个 TCP 连接上仍然能够发送数据,直到这一方向也发送了 FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭
挥手请求可以是 Client 端,也可以是 Server 端发起的,假设是 Client 端发起
-
第一次挥手
- Client 端发起挥手请求,向 Server 端发出一个 FIN 报文段主动进行关闭连接,此时报文段的 FIN 标志位被设置为 1,此时,Client 端进入 FIN_WAIT_1 状态,这表示 Client 端没有数据要发送给 Server 端了
-
第二次挥手
- Server 端收到了 Client 端发送的 FIN 报文段,向 Client 端返回一个 ACK 报文段,此时报文段的 ACK 标志位被设置为 1,ack 设为 seq+1,Client 端进入 FIN_WAIT_2 状态,Server 端告诉 Client 端,我确认并同意你的关闭请求
-
第三次挥手
- Server 端向 Client 端发送一个 FIN 报文段请求关闭连接,此时报文段的 FIN 标志位被设置为 1,同时 Client 端进入 LAST_ACK 状态
-
第四次挥手
- Client 端收到 Server 端发送的 FIN 报文段后,向 Server 端发送 ACK 报文段(此时报文段的 ACK 标志位被设置为 1),然后 Client 端进入 TIME_WAIT 状态。Server 端收到 Client 端的 ACK 报文段后就关闭连接。此时,Client 端等待 2MSL 时间后依然没有收到回复,则证明 Server 端已正常关闭,则 Client 端也关闭连接
总结:TCP 数据传输整个过程
7.5 TCP 状态说明
- CLOSED 状态
- 表示一个初始状态
- LISTENING 状态
- 表示服务器端的某个 SOCKET 处于监听状态,监听客户端的连接请求,可以接受连接了。如:服务器能够提供某种服务,它会监听客户端 TCP 端口的连接请求,处于 LISTENING 状态,端口是开放的,等待被客户端连接
- SYN_SENT 状态 (客户端状态)
- 当客户端调用 connect()函数连接时,它首先会发送 SYN 报文给服务器请求建立连接,因此也随即它会进入到了 SYN_SENT 状态,并等待服务器的发送三次握手中的第 2 个报文。SYN_SENT 状态表示客户端已发送 SYN 报文
- SYN_REVD 状态 (服务端状态)
- 表示服务器接受到了 SYN 报文,正常情况下这个状态是服务器端的 SOCKET 在建立 TCP 连接时的三次握手过程中的一个中间状态,很短暂,基本上用 netstat 很难看到这种状态,除非特意写了一个客户端测试程序,故意将三次 TCP 握手过程中最后一个 ACK 报文不予发送。因此这种状态时,当收到客户端的 ACK 报文后,它会进入到 ESTABLISHED 状态
- ESTABLISHED 状态
- 表示连接已经建立
- FIN_WAIT_1 和 FIN_WAIT_2 状态
- 都是表示等待对方的 FIN 报文
- 这两种状态的区别
- FIN_WAIT_1 状态实际上是当 SOCKET 在 ESTABLISHED 状态时,它想主动关闭连接,向对方发送了 FIN 报文,此时该 SOCKET 即进入到FIN_WAIT_1 状态
- 而当对方回应 ACK 报文后,则进入到 FIN_WAIT_2 状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应 ACK 报文,所以 FIN_WAIT_1 状态一般是比较难见到的,而 FIN_WAIT_2 状态还有时常常可以用 netstat 看到
- TIME_WAIT 状态
- 表示收到了对方的 FIN 报文,并发送出了 ACK 报文,就等 2MSL 后即可回到 CLOSED 可用状态了。如果 FIN_WAIT_1 状态下,收到了对方同时带 FIN 标志和 ACK 标志的报文时,可以直接进入到 TIME_WAIT 状态,而无须经过 FIN_WAIT_2 状态
- CLOSE_WAIT 状态
- 表示在等待关闭。当对方 close 一个 SOCKET 后发送 FIN 报文给自己,你系统毫无疑问地会回应一个 ACK 报文给对方,此时则进入到 CLOSE_WAIT 状态。然后,查看是否还有数据发送给对方,如果没有,则 close 这个 SOCKET,发送 FIN 报文给对方,也即关闭连接,所以在 CLOSE_WAIT 状态下,需要完成的事情是等待你去关闭连接
- LAST_ACK 状态
- 它是被动关闭一方在发送 FIN 报文后,最后等待对方的 ACK 报文。当收到 ACK 报文后,也即可以进入到 CLOSED 状态了
8. UDP 协议
-
UDP(User Datagram Protoco,用户数据报协议),是一种无连接、不可靠的协议,它也工作在传输层
- 它只是简单地实现从一端主机到另一端主机的数据传输功能,这些数据通过 IP 层发送,在网络中传输,到达目标主机的顺序是无法预知的,因此需要应用程序对这些数据进行排序处理,这就带来了很大的不方便
- 此外,UDP 协议没有流量控制、拥塞控制等功能,在发送的一端,UDP 只是把上层应用的数据封装到 UDP 报文中,在差错检测方面,仅仅是对数据进行了简单的校验,然后将其封装到 IP 数据报中发送出去
- 接收端无论是否收到数据,都不会产生一个应答发送给源主机,并且如果接收到数据发送校验错误,那么接收端就会丢弃该 UDP 报文,也不会告诉源主机,因此无法保证传输数据的准确性,只能靠应用程序来保障准确性
-
UDP 协议的特点
- 无连接、不可靠
- 尽可能提供交付数据服务,出现差错直接丢弃且无反馈
- 面向报文,发送方的 UDP 拿到上层数据直接添加一个 UDP 首部,然后进行校验后就递交给 IP 层,而接收的一方在接收到 UDP 报文后简单进行校验,然后直接去除数据递交给上层应用
- 速度快,因为 UDP 协议没有 TCP 协议的握手、确认、窗口、重传、拥塞控制等机制,UDP 是一个无状态的传输协议,所以它在传递数据时非常快,即使在网络拥塞的时候 UDP 也不会降低发送的数据
- UDP 协议应用于对传输速度有要求,并且可以容忍出现差错的数据传输中,如:实时直播、网络电话等
9. 端口号
- 互联网中的每一台主机都需要一个唯一的 IP 地址以标识自己的身份,网络中传输的数据包通过 IP 地址找到对应的目标主机,一台主机通常只有一个 IP 地址,但主机上运行的网络进程却通常不止一个,如:Windows 电脑上运行着 QQ、微信、钉钉、网页浏览器等,这些进程都需要进行网络连接,它们都可通过网络发送/接收数据
- 主机接收到网络数据之后,如何确定该数据是哪个进程对应的接收数据呢?
- 通过端口号来确定
- 端口号本质上就是一个数字编号,用来在一台主机中唯一标识一个能上网(能够进行网络通信)的进程
- 端口号的取值范围为 0~65535
- 一台主机通常只有一个 IP 地址,但是可能有多个端口号,每个端口号表示一个能上网的进程
- 一台拥有 IP 地址的主机可以提供许多服务,比如 Web 服务、FTP 服务、SMTP 服务等,这些服务都是能够进行网络通信的进程
- IP 地址只能区分网络中不同的主机,并不能区分主机中的这些进程,显然不能只靠 IP 地址,因此才有了端口号,通过 “IP 地址 + 端口号” 来区分主机不同的进程
总结
- IP 地址:可以在网络环境中,唯一标识一台主机
- 端口号:可以在网络的一台主机上,唯一标识一个进程
- IP 地址 + 端口号:可以在网络环境中,唯一标识一个进程
- 常见服务的默认端口号