网络发展
- 独立模式:计算机之间相互独立;
- 网络互联:多台计算机连接在一起,完成数据共享;
- 局域网:计算机数量更多了,所以通过交换机和路由器连接在一起;
- 广域网:将远隔千里的计算机都连接在一起;
网络协议
概念
- 原因:计算机生产厂商有很多,计算机操作系统种类也有很多,计算机网络硬件设备种类还是有很多,那么如何让这些不同厂商之间生产的计算机能够相互顺畅的通信? 这就需要有人站出来,约定一个共同的标准,大家都来遵守,这就是网络协议;
- 方式:计算机之间的传输媒介是光信号和电信号,通过 “频率” 的 “强弱” 来表示 0 和 1 这样的信息,要想传递各种不同的信息,就需要约定好双方的数据格式;
协议分层
- 概念:在复杂的网络通信环境中,根据服务以及所使用的协议,将网络通信环境划分为多层;
- 原理:将原本复杂的问题划分为许多相对独立的模块,模块与模块之间的相关性很小,但是互相又可以组合起来成为一个完整的整体;
这大概类似于一个完整的程序——我们通过许多类将不同的对象封装起来,然后再将这些类组合在一起,最终实现了一个程序的功能; - 分类:现如今有两种分类——OSI 七层模型、TCP/IP 五层(四层)模型;
OSI 七层模型
- 概念:OSI(Open System Interconnection,开放系统互连)七层网络模型称为开放式系统互联参考模型,是一个逻辑上的定义和规范,把网络从逻辑上分为了 7 层,每一层都有相关、相对应的物理设备;
- 特性:OSI 七层模型是一种框架性的设计方法,其最主要的功能使就是帮助不同类型的主机实现数据传输,它的最大优点是将服务、接口和协议这三个概念明确地区分开来,概念清楚,理论也比较完整,通过七个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯;
- 说明:该模型由于划分的太细致,导致实现起来过于复杂,所以并不适用,因此大佬们又设计出了 TCP/IP 模型,该模型在实际中应用场景非常多;
TCP/IP 五层(四层)模型
- 概念:TCP/IP 是一组协议的代名词,它还包括许多协议,组成了 TCP/IP 协议簇,TCP/IP 通讯协议采用了 5 层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求,通常由于物理层我们考虑的比较少,因此很多时候也可以称为 TCP/IP 四层模型;
- 物理层:负责光/电信号的传递方式,比如现在以太网通用的网线(双绞线)、早期以太网采用的同轴电缆(现在主要用于有线电视)、光纤,现在的 wifi 无线网使用的电磁波等都属于物理层的概念,物理层的能力决定了最大传输速率、传输距离、抗干扰性等,硬件有——集线器 (Hub);
- 数据链路层:负责设备之间的数据帧的传送和识别,例如网卡设备的驱动、帧同步(就是说从网线上检测到什么信号算作新帧的开始)、冲突检测(如果检测到冲突就自动重发)、数据差错校验等工作,在该层有以太网、令牌环网、无线 LAN 等多种标准,硬件有——交换机 (Switch);
- 网络层:负责地址管理和路由选择,例如在 IP 协议中,通过 IP 地址来标识一台主机,并通过路由表的方式规划出两台主机之间的数据传输的线路(路由),硬件有——路由器 (Router);
- 传输层:负责两台主机之间的数据传输,如传输控制协议 (TCP),能够确保数据可靠的从源主机发送到目标主机;
- 应用层:负责应用程序间沟通,如简单电子邮件传输(SMTP)、文件传输协议(FTP)、网络远程访问协议(Telnet)等,我们的网络编程主要就是针对应用层;
说明
- 一般来说:
- 对于一台主机,它的操作系统内核实现了从传输层到物理层的内容;
- 对于一台路由器,它实现了从网络层到物理层;
- 对于一台交换机,它实现了从数据链路层到物理层;
- 对于集线器,它只实现了物理层;
- 但是并不绝对,很多交换机也实现了网络层的转发;很多路由器也实现了部分传输层的内容(比如端口转发);
网络传输基本流程
网络传输流程图
- 同一网段内的两台主机进行文件传输:在网段内直接传输;
- 跨网段的两台主机进行的文件传输:需要经过一个或多个路由器;
数据的包封装和分用
概念
- 不同的协议层对数据包有不同的称谓,在传输层叫做段 (segment),在网络层叫做数据报 (datagram),在链路层叫做帧 (frame);
- 应用层数据通过协议栈发到网络上时,每层协议都要加上一个数据首部 (header),该过程称为封装 (Encapsulation);
- 首部信息中包含了一些类似于首部有多长、载荷 (payload) 有多长、上层协议是什么等信息;
- 数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部,根据首部中的 “上层协议字段” 将数据交给对应的上层协议处理,该过程称为分用 (Demultiplexing);
数据封装
数据分用
一些概念
端口
- 概念:端口(port)在一台计算机上用于标识一个网络通信的进程(实际上是标识进程中的一个套接字),具体作用是,当网卡接收到网络中发往当前主机的一条数据后,端口决定这条数据由该主机上的哪个进程处理,因此网络中的每条数据都包含的信息其中两条是:源端端口 + 对端端口;
- 性质:是一个 uint16_t 类型的整数(无符号 16 位的整数),一个端口只能被一个进程占用,但是一个进程可以使用多个端口;
- 端口号与进程ID:我们之前在学习系统编程的时候, 学习了 pid 能唯一的标识一个进程,而此时学习的的端口号也是唯一表示一个进程,那么这两者之间是怎样的关系?
在一个主机上,一个进程在被多次创建时,每一次的 ID 都不一定是相同的,而端口号每一次却是确定且唯一的;
IP地址
- 概念:IP 地址是网络中每一台主机的唯一标识,分为 IPV4 与 IPV6,在网络中通信的每一条数据都会拥有的信息其中两条是:源端 IP 地址 + 对端 IP 地址(发送端 + 接收端);
- 功能:因为互联网错综复杂,一条数据如果不知道接受者是谁,那么就无法送达,如果不知道发出者是谁,那么就无法回复,所以存在了 IP 地址的概念,使得每一个互联网在线的主机都是唯一的,这样就可以精准的进行数据的传输;
- 行为:在数据封装过程中,在 IP 数据包头部中,有两个 IP 地址,分别叫做源 IP 地址,和目的 IP 地址;
- IPV4:是 uint32_t 类型的整数(无符号 32 位的整数),通常用点分十进制的字符串表示,用点分割的每一个数字表示一个字节,范围是 0 - 255(例如:192.168.0.1),也就是说最多可以表示四十二亿多用户共同互联网在线,但是随着时代的进步,共同互联网的人数越来越多,这些四十二亿多的 IP 地址早已不够用,所以在 IPV4 的基础上诞生了一些新的技术:
- DHCP:即时分配 IP 地址,也就是说当你的主机进入了互联网,那么就为你分配一个固定的 IP 地址,如果没有连入互联网,那么也就没有被分配;
- NAT:在互联网这个公网下再组建许多私网,私网中连接的主机被分配的是私网中特有的 IP 地址,不同私网下的 IP 地址可以重复,这就和 C++ 中的命名空间一样:同一作用域下不能出现相同的函数,但是在不同作用域下可以出现相同函数;
- NAPT:与 NAT 技术基本相同,只是在组建私网后,在进行数据通信时会建立转换的映射关系,以方便数据在回复时通过网关能够找到相对应的私网主机;
- IPV6:是 uint8_t addr[16] 类型数据(128位的整数),他可以表示非常多的 IP 地址,足够我们每人分配一个并且可以使用很长一段时间,虽然该 IP 可以做到每人一个,但是由于不兼容 IPV4,所以直到如今,使用的人并不是很多,还是以 IPV4 为主;
MAC地址
- 概念:在网络中数据的传输并不一定可以直接由源端端口到达对端端口,这中间往往需要经过许多其他端口的转接,在这传输的过程中,相邻端口之间的数据传输需要 MAC 地址的识别才能完成;
- 类型:长度为 48 位无符号整型数据,一般用 16 进制数字加上冒号的形式来表示,例如:
08:00:27:03:fb:19
; - 特性:MAC 地址在网卡出厂时就确定了,不能修改,且 MAC 地址通常是唯一的,不过虚拟机中的 MAC 地址不是真实的 MAC 地址,可能会冲突,也有些网卡支持用户配置 MAC 地址;
- 疑问:既然有了 IP 地址,为什么还要 MAC 地址呢?
这是由组网方式决定的,如今比较流行的接入 Internet 的方式(也是未来发展的方向)是把主机通过局域网组织在一起,然后再通过交换机和 Internet 相连接。这样一来就出现了如何区分具体用户,防止盗用的问题。由于 IP 只是逻辑上标识,任何人都随意修改,因此不能用来标识用户;而 MAC 地址则不然,它是固化在网卡里面的,从理论上讲,除非盗来硬件(网卡),否则是没有办法冒名顶替的,另外还有一些其他原因,这些后面会提到的;
网络字节序
- 概念:字节序就是 CPU 对内存中数据进行存取的顺序;
- 分类:(具体看我这篇博客——数据的存储)
- 大端字节序:低地址存高位,高地址存低位;
- 小端字节序:低地址存低位,高地址存高位;
- 影响:通信两端的主机字节序的不同可能会导致数据的二义性,例如源端是小端字节序发送,对端是大端字节序进行接收,那么对该数据访问处理后,结果就会出问题了;
- 解决:定义网络字节序的标准,网络中的数据必须都是网络字节序——大端字节序,在进行通信时,发送方将数据转换为网络字节序的数据后进行发送,接收方接收到数据后明确知道你这是大端字节序,所以转换为自己主机的字节序,然后处理;
- 哪些数据类型需要注意该问题?
- 存储单元大于一个字节的数据类型都要注意该问题:
short
、int
、long
、float
、double
; - 存储单元等于一个字节的数据类型:
char
、char*
;
- 存储单元大于一个字节的数据类型都要注意该问题:
- 接口:
uint32_t htonl(uint32_t hostlong);
:32 位数据,主机字节序到网络字节序的转换;uint16_t htons(uint16_t hostshort);
:16 位数据,主机字节序到网络字节序的转换;uint32_t ntonl(uint32_t netlong);
:32 位数据,网络字节序到主机字节序的转换;uint16_t ntons(uint32_t netlong);
:16 位数据,网络字节序到主机字节序的转换;
- 接口注意事项:
- 这些函数名很好记,h 表示 host,n 表示 network,l 表示 32 位长整数,s 表示 16 位短整数,例如 htonl 表示将 32 位的长整数从主机字节序转换为网络字节序;
- 如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回;
- 如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回;