Linux网络--网络基础概念
大家好,今天我们开启新的学习:Linux的网络部分。那么我们话不多说,直接开始今天的学习。
1. 计算机网络背景
1.1 网络发展
独立模式: 计算机之间相互独立

网络互联: 多台计算机连接在一起, 完成数据共享

局域网 LAN: 计算机数量更多了, 通过交换机和路由器连接在一起

广域网 WAN: 将远隔千里的计算机都连在一起

计算机是人的工具,人要协同工作,注定了网络的产生是必然的
2. 初识协议

计算机之间的传输媒介是光信号和电信号. 通过 "频率" 和 "强弱" 来表示 0 和 1 这样的信息。要想传递各种不同的信息, 就需要约定好双方的数据格式
定好协议,但是你用频率表示 01,我用强弱表示 01,就好比我用中国话,你用英语一样,虽然大家可能遵守的一套通信规则,但是语言不同,即是订好了基本的协议,也是无法正常通信的
计算机生产厂商有很多;计算机操作系统, 也有很多;计算机网络硬件设备, 还是有很多;如何让这些不同厂商之间生产的计算机能够相互顺畅的通信? 就需要有人站出来, 约定一个共同的标准, 大家都来遵守, 这就是 网络协议;
想制定一套大家都能来遵守的协议,那么该协议的制定者肯定要有一定的话语权
国际标准化组织:IEEE(电气和电子工程师协会):这是一个由计算机和工程领域专家组成的庞大技术组织,在通信协议领域贡献突出。IEEE 制定了全世界电子、电气和计算机科学领域 30%左右的标准,包括 IEEE 802 系列标准,这些标准涵盖了从局域网(LAN)到广域网(WAN)等多种网络技术。ISO(国际标准化组织):ISO 是由多个国家的标准化团体组成的国际组织,它在开放系统互连(OSI)模型方面的工作尤为著名。OSI 模型定义了网络通信的七层协议结构,尽管在实际应用中,TCP/IP 协议族更为普遍,但 OSI 模型仍然在学术和理论研究中占有重要地位。ITU(国际电信联盟):ITU 是联合国下属的专门机构,负责制定电信领域的国际标准。ITU-T 制定的标准涵盖了电话和网络通信,与 ISO 合作确保了通信技术的全球兼容性和互操作性
有关通信的协议就是由ISO建立的OSI协议
2.1 协议分层
协议本质也是软件,在设计上为了更好的进行模块化,解耦合,也是被设计成为层状结构的
2.1.1 软件分层的好处

在这个例子中, 我们的"协议"只有两层:语言层、通信设备层,但是实际的网络通信协议,设计的会更加复杂, 需要分更多的层但是通过上面的简单例子,我们是能理解,分层可以实现解耦合,让软件维护的成本更低
2.2 OSI 七层模型
OSI(Open System Interconnection,开放系统互连)七层网络模型称为开放式系统互联参考模型,是一个逻辑上的定义和规范;把网络从逻辑上分为了 7 层. 每一层都有相关、相对应的物理设备,比如路由器,交换机;OSI 七层模型是一种框架性的设计方法,其最主要的功能使就是帮助不同类型的主机实现数据传输;它的最大优点是将服务、接口和协议这三个概念明确地区分开来,概念清楚,理论也比较完整. 通过七个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯; 但是, 它既复杂又不实用; 所以我们按照 TCP/IP 四层模型来讲解


其实在网络角度,OSI 定的协议 7 层模型其实非常完善,但是在实际操作的过程中,会话层、表示层是不可能接入到操作系统中的,所以在工程实践中,最终落地的是 5 层协议。
2.3 TCP/IP 五层模型
TCP/IP 是一组协议的代名词,它还包括许多协议,组成了 TCP/IP 协议簇.TCP/IP 通讯协议采用了 5 层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求.
物理层: 负责光/电信号的传递方式. 比如现在以太网通用的网线(双绞 线)、早期以太网采用的的同轴电缆(现在主要用于有线电视)、光纤, 现在的 wifi 无线网使用电磁波等都属于物理层的概念。物理层的能力决定了最大传输速率、传输距离、抗干扰性等. 集线器(Hub)工作在物理层.数据链路层: 负责设备之间的数据帧的传送和识别. 例如网卡设备的驱动、帧同步(就是说从网线上检测到什么信号算作新帧的开始)、冲突检测(如果检测到冲突就自动重发)、数据差错校验等工作. 有以太网、令牌环网, 无线 LAN 等标准. 交换机(Switch)工作在数据链路层.网络层: 负责地址管理和路由选择. 例如在 IP 协议中, 通过 IP 地址来标识一台主机, 并通过路由表的方式规划出两台主机之间的数据传输的线路(路由). 路由器(Router)工作在网路层.传输层: 负责两台主机之间的数据传输. 如传输控制协议 (TCP), 能够确保数据可靠的从源主机发送到目标主机.应用层: 负责应用程序间沟通,如简单电子邮件传输(SMTP)、文件传输协议(FTP)、网络远程访问协议(Telnet)等. 我们的网络编程主要就是针对应用层

对于一台主机, 它的操作系统内核实现了从传输层到物理层的内容;对于一台路由器, 它实现了从网络层到物理层;对于一台交换机, 它实现了从数据链路层到物理层;对于集线器, 它只实现了物理层;
3. 再识协议
上面的内容,我们只是懂了一些基本概念,还是达不到我们的目标,下面我们再次重新理解协议和协议分层。
3.1 为什么要有 TCP/IP 协议?
首先,即便是单机,你的计算机内部,其实都是存在协议的,比如:其他设备和内存通信,会有内存协议。其他设备和磁盘通信,会有磁盘相关的协议,比如:SATA,IDE,SCSI 等。只不过我们感知不到罢了。而且这些协议都在本地主机各自的硬件中,通信的成本、问题比较少。其次,网络通信最大的特点就是主机之间变远了。任何通信特征的变化,一定会带来新的问题,有问题就得解决问题,所以需要新的协议咯。

所以,为什么要有 TCP/IP 协议?本质就是通信主机距离变远了
3.2 什么是 TCP/IP 协议?
TCP/IP 协议的本质是一种解决方案TCP/IP 协议能分层,前提是因为问题们本身能分层
3.3 TCP/IP 协议与操作系统的关系(宏观上,怎么实现的)
因为无论是计算机厂家还是操作系统厂家,都要遵循那套协议,所以不管是Windows系统,Linux系统,还是Mac系统,它们在网络协议栈这方面的内容必须是一样的,所以各主机间能够通信。

TCP协议是传输层的协议,IP协议是网络层的协议,这两层直接和操作系统关联,所以也被放在一起说了
所以主机间的通信,本质上也就是协议栈间的通信
3.4 所以究竟什么是协议?
截止到目前,我们还没接触过任何协议,但是如何朴素的理解协议,我们已经可以试试了。

因为网络协议栈是相同的,所以一台主机以某种方式打包的数据,在发送到其他主机上后,一定能通过同样的解包方式将数据还原出来。也就是说,用同样的代码实现协议,用同样的自定义数据类型,天然就具有”共识“,能够识别对方发来的数据,这不就是约定吗?
关于协议的朴素理解:所谓协议,就是通信双方都认识的结构化的数据类型因为协议栈是分层的,所以每层的双方都有协议,同层之间,互相可以认识对方的协议。
我在网上买了东西,拿到货的时候,快递单上不仅有厂家和收货人的信息,还会有许多其他信息,这些信息其实就是一层层的协议
4. 网络传输基本流程
4.1 局域网网络传输流程图
4.1.1 局域网(以太网为例)通信原理
主要的局域网有以下几种:
以太网
无线LAN
令牌环网
下面就以以太网来举例:
原理类似上课,学生和老师在同一个教室里,老师讲课,学生提问都能直接被对方听到。所以两台主机在同一个局域网,也是能够直接通信的
4.1.2 认识 MAC 地址
MAC 地址用来识别数据链路层中相连的节点; 长度为 48 位及 6 个字节一般用 16 进制数字加上冒号的形式来表示(例如: 08:00:27:03:fb:19)在网卡出厂时就确定了, 不能修改. mac 地址通常是唯一的(虚拟机中的 mac 地址不是真实的 mac 地址, 可能会冲突; 也有些网卡支持用户配置 mac 地址)

以太网中,任何时刻,只允许一台机器向网络中发送数据如果有多台同时发送,会发生数据干扰,我们称之为数据碰撞所有发送数据的主机要进行碰撞检测和碰撞避免没有交换机的情况下,一个以太网就是一个碰撞域局域网通信的过程中,主机对收到的报文确认是否是发给自己的,是通过目标mac地址判定这里可以试着从系统角度来理解局域网通信原理
其次,一台主机在发送数据时,局域网内其他主机都会收到该数据,但通过比对mac地址来确定是否接受,这一过程叫做泛洪
对于其他两种网络,无线LAN只是不用网线,比如我们电脑手机连的WIFI。而令牌环网是只有持有令牌的主机才能发送数据,类似之前学过的锁。



报头部分,就是对应协议层的结构体字段,我们一般叫做报头除了报头,剩下的叫做有效载荷故,报文 = 报头 + 有效载荷
不同的协议层对数据包有不同的称谓,在传输层叫做段(segment),在网络层叫做数据报 (datagram),在链路层叫做帧(frame).应用层数据通过协议栈发到网络上时,每层协议都要加上一个数据首部(header),称为封装(Encapsulation).首部信息中包含了一些类似于首部有多长, 载荷(payload)有多长, 上层协议是什么等信息.数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部,根据首部中的 "上层协议字段" 将数据交给对应的上层协议处理

在网络传输的过程中,数据不是直接发送给对方主机的,而是先要自定向下将数据交付给下层协议,最后由底层发送,然后由对方主机的底层来进行接受,在自底向上进行向上交付,下面是一张示意图。
4.1.3 数据包封装和分用


从今天开始,我们学习任何协议,都要先宏观上建立这样的认识:要学习的协议,是如何做到解包的?只有明确了解包,封包也就能理解要学习的协议,是如何做到将自己的有效载荷,交付给上层协议的?
4.2 跨网络传输流程图
4.2.1 网络中的地址管理 - 认识 IP 地址
IP 协议有两个版本, IPv4 和 IPv6. 我们整个的课程, 凡是提到 IP 协议, 没有特殊说明的, 默认都是指 IPv4
IP 地址是在 IP 协议中, 用来标识网络中不同主机的地址;对于 IPv4 来说, IP 地址是一个 4 字节, 32 位的整数;我们通常也使用 "点分十进制" 的字符串表示 IP 地址, 例如 192.168.0.1 ; 用点分割的每一个数字表示一个字节, 范围是 0 - 255;
IPv4地址一共32位,若是每台主机都要分配IP地址的话,那么IP地址就不够用了,所以现在有了IPv6,IPv6地址是128位的,短时间内不用再担心地址用完的问题
跨网段的主机的数据传输. 数据从一台计算机到另一台计算机传输过程中要经过一个或多个路由器

IP 地址在整个路由过程中,一直不变(目前,我们只能这样说明,后面再修正)Mac 地址一直在变目的 IP 是一种长远目标,Mac 是下一阶段目标,目的 IP 是路径选择的重要依据,mac 地址是局域网转发的重要依据

路由器连接了不同的局域网,数据会先发送到路由器,再解包重新封装发送到目的地


IP 网络层存在的意义:提供网络虚拟层,让世界的所有网络都是 IP 网络,屏蔽最底层网络的差异
5. Socket 编程预备
5.1 理解源 IP 地址和目的 IP 地址
IP 在网络中,用来标识主机的唯一性
不是的。因为数据是给人用的。比如:聊天是人在聊天,下载是人在下载,浏览网页是人在浏览?但是人是怎么看到聊天信息的呢?怎么执行下载任务呢?怎么浏览网页信息呢?通过启动的 qq,迅雷,浏览器。而启动的 qq,迅雷,浏览器都是进程。换句话说,进程是人在系统中的代表,只要把数据给进程,人就相当于就拿到了数据。
所以:数据传输到主机不是目的,而是手段。到达主机内部,在交给主机内的进程,才是目的。但是系统中,同时会存在非常多的进程,当数据到达目标主机之后,怎么转发给目标进程?这就要在网络的背景下,在系统中,标识主机的唯一性。

5.2 认识端口号
端口号(port)是传输层协议的内容
端口号是一个 2 字节 16 位的整数;端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理;IP 地址 + 端口号能够标识网络上的某一台主机的某一个进程;一个端口号只能被一个进程占用

5.2.1 端口号范围划分
0 - 1023: 知名端口号, HTTP, FTP, SSH 等这些广为使用的应用层协议, 他们的端口号都是固定的.1024 - 65535: 操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的.
5.2.2 理解 "端口号" 和 "进程 ID"
另外, 一个进程可以绑定多个端口号; 但是一个端口号不能被多个进程绑定;进程 ID 属于系统概念,技术上也具有唯一性,确实可以用来标识唯一的一个进程,但是这样做,会让系统进程管理和网络强耦合,实际设计的时候,并没有选择这样做。
5.2.3 理解源端口号和目的端口号
传输层协议(TCP 和 UDP)的数据段中有两个端口号, 分别叫做源端口号和目的端口号.就是在描述 "数据是谁发的, 要发给谁";
5.2.4 理解 socket
IP 地址用来标识互联网中唯一的一台主机,port 用来标识该主机上唯一的一个网络进程IP+Port 就能表示互联网中唯一的一个进程所以,通信的时候,本质是两个互联网进程代表人来进行通信,{srcIp,srcPort,dstIp,dstPort}这样的 4 元组就能标识互联网中唯二的两个进程所以,网络通信的本质,也是进程间通信我们把 ip+port 叫做套接字 socket
5.3 传输层的典型代表
如果我们了解了系统,也了解了网络协议栈,我们就会清楚,传输层是属于内核的,那么我们要通过网络协议栈进行通信,必定调用的是传输层提供的系统调用,来进行的网络通信。

5.3.1 认识 TCP 协议
传输层协议有连接可靠传输面向字节流
5.3.2 认识 UDP 协议
传输层协议无连接不可靠传输面向数据报
5.4 网络字节序
我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分, 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分, 网络数据流同样有大端小端之分. 那么如何定义网络数据流的地址呢?
1. 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出;2. 接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存;3. 因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址.4. TCP/IP 协议规定,网络数据流应采用大端字节序,即低地址高字节.5. 不管这台主机是大端机还是小端机, 都会按照这个 TCP/IP 规定的网络字节序来发送/接收数据;6. 如果当前发送主机是小端, 就需要先将数据转成大端; 否则就忽略, 直接发送即可;

为使网络程序具有可移植性,使同样的 C 代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。

这些函数名很好记,h 表示 host,n 表示 network,l 表示 32 位长整数,s 表示 16 位短整数。例如 htonl 表示将 32 位的长整数从主机字节序转换为网络字节序,例如将 IP 地址转换后准备发送。如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回;如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。
5.5 socket 编程接口
5.5.1 socket 常见 API
// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);// 绑定端口号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address, socklen_t address_len);// 开始监听 socket (TCP, 服务器)
int listen(int socket, int backlog);// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address, socklen_t* address_len);// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);5.5.2 sockaddr 结构
socket API 是一层抽象的网络编程接口,适用于各种底层网络协议,如 IPv4、IPv6,以及后面要讲的 UNIX Domain Socket. 然而, 各种网络协议的地址格式并不相同

IPv4 和 IPv6 的地址格式定义在 netinet/in.h 中,IPv4 地址用 sockaddr_in 结构体表示,包括 16 位地址类型, 16 位端口号和 32 位 IP 地址.IPv4、IPv6 地址类型分别定义为常数 AF_INET、AF_INET6. 这样,只要取得某种 sockaddr 结构体的首地址,不需要知道具体是哪种类型的 sockaddr 结构体,就可以根据地址类型字段确定结构体中的内容.socket API 可以都用 struct sockaddr *类型表示, 在使用的时候需要强制转化成sockaddr_in; 这样的好处是程序的通用性, 可以接收 IPv4, IPv6, 以及 UNIX Domain Socket 各种类型的 sockaddr 结构体指针做为参数;


虽然 socket api 的接口是 sockaddr, 但是我们真正在基于 IPv4 编程时, 使用的数据结构是 sockaddr_in; 这个结构里主要有三部分信息: 地址类型, 端口号, IP 地址

in_addr 用来表示一个 IPv4 的 IP 地址. 其实就是一个 32 位的整数;
今天的内容我们先来大体介绍一下网络部分,后面在一一学习,今天的内容就是这些,我们下次再见!
