计算机网络 : 网络基础
计算机网络 : 网络基础
目录
- 计算机网络 : 网络基础
- 引言
- 1. 网络发展背景
- 2. 初始协议
- 2.1 初始协议
- 2.2 协议分层
- 2.2.1 软件分层的好处
- 2.2.2 OSI七层模型
- 2.2.3 TCP/IP五层(四层)模型
- 2.3 `TCP/IP`协议
- 2.3.1`TCP/IP`协议与操作系统的关系(宏观)
- 2.4 网络传输基本流程
- 2.4.1 局域网网络传输流程(以太网)
- 2.4.2 数据包封装和分用
- 2.4.3 跨网络传输流程
- 3. Socket编程预备
- 3.1 认识端口号
- 3.2 传输层的典型代表
- 3.3 网络字节序
- 3.4 `socket`编程接口
引言
本博客将系统介绍计算机网络的基础知识,包括网络的发展背景、核心协议(如TCP/IP
)、协议分层模型(OSI与TCP/IP
)、网络传输流程(局域网与跨网络通信)以及Socket
编程的基本概念。无论你是初学者还是希望巩固基础的技术爱好者,都能从这里获得清晰的网络知识框架和实践指导。
1. 网络发展背景
-
独立模式:计算机之间相互独立
-
网络互联:多台计算机连接在一起,完成数据共享
-
局域网LAN:计算机数量更多了,通过交换机和路由器连接在一起
-
广域网WAN:将远隔千里的计算机都连在了一起
-
所谓局域网和广域网都只是一个相对的概念。
-
计算机是人的工具,人要协同工作,就注定计算机中网络的产生是必然的。
-
网络的发展一直都是从局部到整体。而整体记性通信靠的是
ip
地址,网络中一切皆IP
。
2. 初始协议
2.1 初始协议
-
协议是一种约定
-
举例:
计算机之间的传输媒介是光信号和电信号,通过 频率 和 强弱 来表示 0 和 1 这样的信息。要想传递各种不同的信息,就需要约定好双方的数据格式。
思考:只要通信的两台主机约定好协议就可以了吗?如果仅定好协议,但你用频率表示 01,我用强弱表示 01,就好比我用中文,你用葡萄牙语一样,虽然双方可能遵守一套通信规则,但语言不同,即使订好了基本协议,也无法正常通信。
因此,完善的协议需要更细致的规定,并确保所有参与者都严格遵守。计算机生产厂商众多,操作系统和网络硬件设备也各不相同,如何让不同厂商生产的计算机能够顺畅通信?这就需要业界共同制定一个统一的标准,即 网络协议。
-
通常,具备制定协议或标准资格的组织或公司必须是业界公认的权威机构。
能定制协议标准的组织或公司主要有以下几类:
国际标准化组织:
**IEEE(电气和电子工程师协会)**是一个由计算机和工程领域专家组成的庞大技术组织,在通信协议领域贡献突出,制定了全世界电子、电气和计算机科学领域约30%的标准,包括IEEE 802系列标准,涵盖从局域网(LAN)到广域网(WAN)等多种网络技术。
**ISO(国际标准化组织)**由多个国家的标准化团体组成,以开放系统互连(OSI)模型著称,该模型定义了网络通信的七层协议结构,尽管TCP/IP协议族更常用,但OSI模型在学术和理论研究中仍占重要地位。
**ITU(国际电信联盟)**是联合国下属的专门机构,负责制定电信领域的国际标准,ITU-T的标准涵盖电话和网络通信,与ISO合作确保全球兼容性和互操作性。
区域标准化组织:
**ETSI(欧洲电信标准学会)**由欧洲共同体各国政府资助,成员包括电信行业的厂商与研究机构,从事从研究开发到标准制定的工作。
**ASTAP(亚洲与泛太平洋电信标准化协会)**于1998年由日本与韩国发起成立,旨在加强亚洲与太平洋地区信息通信基础设施及其相互连接的标准化协作。
公司:某些公司(如泰凌微)自研低功耗蓝牙、Zigbee、Thread及Matter等标准的软件协议栈,并可定制化改动,这是其核心竞争力之一;泰凌微还计划重点发展智能电子价签、智能遥控、智能家居等市场。
民间国际团体:**IETF(互联网工程师任务组)**是负责开发和推广互联网协议(尤其是TCP/IP协议族)的志愿组织,通过RFC发布新协议或更新旧协议标准。
官方机构:**FCC(联邦通信委员会)**是美国管理通信技术的官方机构,主要职责是通过对无线电、电视和有线通信的管理保护公众利益,并对通信产品的技术特性(包括标准化)进行审查和监督。
以上组织或公司均能定制协议标准,以满足特定需求或推动技术发展。
2.2 协议分层
- 协议本质也是软件,在设计上为了更好的进行模块化,解耦合,因此也是被设计成为层状结构的。
2.2.1 软件分层的好处
- 在这个例子中,我们的协议只有两层:语言层和通信设备层。但是实际上的通信协议,设计的会更加复杂,层数会更多。
- 通过上面的例子,我们就可以理解,分层其实就是为了实现解耦合,让软件维护的成本更低
2.2.2 OSI七层模型
- OSI(Open System Interconnection,开放系统互连)七层网络模型 称为开放式系统互联参考模型,是一个逻辑上的定义和规范。
- 把网络从逻辑上分为了7层,每一层都有相关、相对应的物理设备,比如路由器、交换机。
- OSI七层模型是一种框架性的设计方法,其最主要的功能是帮助不同类型的主机实现数据传输。它的最大优点是将服务、接口和协议这三个概念明确地区分开来,概念清楚,理论也比较完整,通过七个层次化的结构模型使不同的系统、不同的网络之间实现可靠的通讯。
- 在网络角度,OSI设定的7层协议模型是非常完善的,但是在实际操作的过程中,会话层、表示层是不可能接入到操作系统中的,所以在工程实践中,最终落地的是5层协议。不过由于它既复杂又不实用,所以我们按照TCP/IP四层模型来讲解。
2.2.3 TCP/IP五层(四层)模型
-
TCP/IP 是一组协议的代名词,它还包括许多协议,组成了 TCP/IP 协议簇。
-
TCP/IP 通讯协议采用了 5 层的层级结构,每一层都调用它的下一层所提供的网络来完成自己的需求。
- 物理层负责光/电信号的传递方式,比如现在以太网通用的网线(双绞线)、早期以太网采用的同轴电缆(现在主要用于有线电视)、光纤,以及现在的 Wi-Fi 无线网使用的电磁波等都属于物理层的概念。物理层的能力决定了最大传输速率、传输距离、抗干扰性等,集线器(Hub)工作在物理层。
- 数据链路层负责设备之间的数据帧的传送和识别,例如网卡设备的驱动、帧同步(检测信号以确定新帧的开始)、冲突检测(检测到冲突时自动重发)、数据差错校验等工作,常见的标准包括以太网、令牌环网和无线 LAN,交换机(Switch)工作在数据链路层。
- 网络层负责地址管理和路由选择,例如在 IP 协议中,通过 IP 地址标识主机,并利用路由表规划数据传输路径,路由器(Router)工作在网络层。
- 传输层负责两台主机之间的数据传输,如传输控制协议(TCP)确保数据可靠地从源主机发送到目标主机。
- 应用层负责应用程序间的通信,如简单邮件传输协议(SMTP)、文件传输协议(FTP)、网络远程访问协议(Telnet)等,网络编程主要针对应用层。
物理层我们考虑的比较少,我们只考虑软件相关的内容,因此很多时候我们直接称为TCP/IP
四层模型。
一般而言
- 对于一台主机,它的操作系统内核实现了从传输层到物理层的内容;
- 对于一台路由器,它实现了从网络层到物理层;
- 对于一台交换机,它实现了从数据链路层到物理层;
- 对于集线器,它只实现了物理层。
但是并不绝对,很多交换机也实现了网络层的转发;;很多路由器也实现了部分传输层的内容(比如端口转发)。
2.3 TCP/IP
协议
-
TCP/IP
协议出现的原因就是因为通信主机距离变远了。任何通信特征的变化,一定会带来新的问题,有问题就得解决问题,所以需要新的协议。 -
TCP/IP
协议的本质就是一种解决方案,TCP/IP
协议能分层的前提是因为问题们本身能分层。
2.3.1TCP/IP
协议与操作系统的关系(宏观)
问题:主机 B 能识别 data,并且准确提取 a=10,b=20,c=30 吗?
回答:答案是肯定的!因为双方都有同样的结构体类型 struct protocol
。也就是说,用同样的代码实现协议,用同样的自定义数据类型,天然就具有“共识”,能够识别对方发来的数据,这就是约定。
关于协议的朴素理解:所谓协议,就是通信双方都认识的结构化的数据类型。因为协议栈是分层的,所以每层都有双方共同遵守的协议,同层之间可以互相理解对方的协议。
2.4 网络传输基本流程
2.4.1 局域网网络传输流程(以太网)
-
两台主机在同一个局域网,是能够直接通信的。
-
每台主机在局域网上,要有唯一的标识来保证主机的唯一性:
mac
地址。 -
认识MAC地址
- MAC地址用来识别数据链路层中相连的节点。
- 长度为48位(即6个字节),通常以16进制数字加冒号的形式表示(例如:08:00:27:03:fb:19)。
- MAC地址在网卡出厂时确定且一般不能修改,通常是唯一的(但虚拟机中的MAC地址并非真实地址可能冲突,部分网卡也支持用户配置MAC地址)。
-
局域网传输流程图
- 以太网中,任何时刻,只允许一台机器向网络中发送数据(因为以太网本质就是共享资源具有互斥属性);以太网中所有主机都会收到信息(泛洪)。
- 如果有多台同时发送,会发生数据干扰,我们称之为数据碰撞。
- 所有发送数据的主机要进行碰撞检测和碰撞避免。
- 没有交换机的情况下,一个以太网就是一个碰撞域。
- 局域网通信的过程中,主机对收到的报文确认是否是发给自己的,是通过目标 MAC 地址判定。
-
同一网段内的两台主机进行发送信息的过程
主机之间的通信:我们必须认识到,本质是两个协议栈在通信。
而其中每层都有协议,所以当我进行上述流程过程的时候,要进行封装和解包。
接受信息的主机中将网卡和数据链路层切换到混杂模式,就可以接受所有主机发送的信息,而不进行判断是否是发送个自己的。(抓包工具的原理)
-
概念:
- 报头部分,就是对应协议层的结构体字段,我们一般叫做报头。
- 除去报头部分,剩下的叫做有效载荷。
- 报文 = 报头 + 有效载荷
-
不同层完整报文的叫法
- 不同的协议层对数据包有不同的称谓,在传输层叫做段(segment);
- 在网络层叫做数据报(datagram);
- 在链路层叫做帧(frame);
- 应用层数据通过协议栈发到网络上时,每层协议都要加上一个数据首部(header),称为封装(Encapsulation)。
- 首部信息中包含了一些类似于首部有多长、载荷(payload)有多长、上层协议是什么等信息。
- 数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部,根据首部中的"上层协议字段"将数据交给对应的上层协议处理。
-
-
结论:
- 在网络传输的过程中,数据不是直接发送给对方主机的,而是先要自顶向下将数据交付给下层协议进行封装,最后由底层发送,然后由对方主机的底层来进行接受,再自底向上进行向上交付。
- 自顶向下封装的意义就是必须贯穿到操作系统,贯穿协议栈,OS是硬件(网卡)的管理者。
- 不考虑应用层协议的情况下,任何协议都满足2点:1.报头必须具有和有效载荷进行分离的能力。2.报头中必须包含,如何将自己的有效载荷,交付给上层的哪一个具体协议。
- 底层收到报文,会进行判断此报文是否是发送给自己的,如不是数据链路层会直接丢弃。
- 协议栈:自顶向下封装就是协议栈将报头入栈的过程;自下向上解包分用就是出栈的过程。
-
2.4.2 数据包封装和分用
-
数据封装的过程
-
数据分用的过程
-
接下来的协议学习,我们在宏观上都应该建立一个认识:
- 要学习的协议,是如何做到解包的?只有明确了解包,封包也就能理解。
- 要学习的协议,是如何做到将自己的有效载荷,交付给上层协议的?
2.4.3 跨网络传输流程
-
网络中的地址管理——认识IP地址
- IP协议有两个版本,
IPV4和IPV6
,本作者关于计网的博客,如没做特殊说明,提到的IP协议默认指的是IPV4
。 - IP 地址是在 IP 协议中用来标识网络中不同主机的地址;
- 对于 IPv4 来说,IP 地址是一个 4 字节、32 位的整数;
- 我们通常也使用"点分十进制"的字符串表示 IP 地址,例如 192.168.0.1,用点分割的每一个数字表示一个字节,范围是 0 - 255。
- 跨网段的主机的数据传输,数据从一台计算机到另一台计算机传输过程中要经过一个或多个路由器。路由器会根据信息的源IP地址和目的IP地址,选择将信息发送到哪个局域网中,通过一个或多个局域网的交接,最终信息到达目的IP地址的主机。
- 电脑和路由器我们都可以看成主机。
- IP协议有两个版本,
-
IP地址的意义
只要有网络层,就会有路由功能。
然后结合封装与解包,体现路由器解包和重新封装的特点。
-
IP地址和Mac地址的区别
- IP地址在整个路由过程中一直保持不变(目前暂作此说明,后续会修正),而MAC地址则会不断变化。
- 目的IP地址代表通信的最终目标,是路径选择的主要依据;
- 而MAC地址则是下一跳的局部目标,是局域网内数据转发的重要依据。
-
路由过程中,IP地址不变,Mac地址一直在变,Mac地址只会在本局域网内有效。
-
网络通信的宏观流程
-
网络层+IP的意义就是:给网络提供了一层虚拟化层,让世界上所有的网络,都叫做IP网络,屏蔽最底层网络的差异。
-
只要IP地址从技术上说是可以的,但是为什么还要Mac地址呢?因为网络是从局部到整体的,是先有局域网的Mac地址再有广域网的IP地址,如果改成只有IP地址,意味着之前的Mac地址全都要换,没有意义,且只有IP地址会带来数据链路层与网络层的强耦合。
-
3. Socket编程预备
3.1 认识端口号
-
首先我们要达成一个共识,数据通过网络传输到主机不是目的,而是手段。到达主机内部,在交给主机内的进程,才是目的。
-
但是在系统中,同时会存在非常多的进程,当数据到达目的主机之后,怎么转发给目标进程?这就要在网络的背景下,在系统中,表示进程的唯一性了。
-
-
端口号(
port
)是传输层协议的内容- 端口号是一个2字节16位的整数。
- 端口号用来表示一个进程,告诉操作系统,当前的这个数据要交给哪一个进程来处理。
- IP地址 + 端口号能够标识网络上的某一台主机的某一个进程。
- 一个端口号只能被一个进程占用,但是一个进程可能有多个端口号。
-
端口号范围划分
0-1023
:知名端口号,HTTP、FTP、SSH等这些广为使用的应用层协议,他们的端口号都是固定的。1024-65535
:操作系统动态分配的端口号,客户端程序的端口号,就是由操作系统从这个范围分配的。
-
理解端口号
port
和进程pid
进程
pid
属于系统概念,技术上也具有唯一性,确实可以用来标识唯一的一个进程,但是不是所有的进程都要进行网络通信,因此不是所有的进程都有端口号。并且如果pid
变化了怎么办?归根结底,端口号的出现就是为了对系统和网络进行解耦。 -
理解源端口号和目的端口号
传输层协议(
TCP
和UDP
)的数据段中有两个端口号,分别叫做源端口号和目的端口号。 就是在描述 “数据是哪个进程发的, 要发给哪个进程”; -
理解
socket
- 综上,
IP
地址用来标识互联网中唯一的一台主机,port
用来标识该主机上唯一的一个网络进程。 IP+Port
就能表示互联网中唯一的一个进程。- 所以,通信的时候,本质是两个互联网进程代表人来进行通信,{
srcIp
,srcPort
,dstIp
,dstPort
}(源IP,源端口号,目的IP,目的端口号)这样的4元组就能标识互联网中唯二的两个进程。 - 所以,网络通信的本质,也是进程间通信。
- 我们把
ip+port
叫做套接字socket
。
- 综上,
3.2 传输层的典型代表
-
如果我们了解了系统,也了解了网络协议栈,我们就会清楚,传输层是属于内核的。那么我们要通过网络协议栈进行通信,必定调用的是传输层提供的系统调用,来进行的网络通信。
-
TCP协议(Transmission Control Protocol 传输控制协议):有传输层协议;有链接;可靠传输;面向字节流。
-
UDP协议(User Datagram Protocol 用户数据报协议):有传输层协议;无连接;不可靠传输;面向数据报。
3.3 网络字节序
-
我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分,磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分,网络数据流同样有大端小端之分。那么如何定义网络数据流的地址呢?
- 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出;
- 接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存;
- 因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址。
- TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。
- 不管这台主机是大端机还是小端机,都会按照这个TCP/IP规定的网络字节序来发送/接收数据;
- 如果当前发送主机是小端,就需要先将数据转成大端;否则就忽略,直接发送即可。
-
为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。
- 这些函数名很好记,
h
表示host
,n
表示network
,l
表示32位长整数,s
表示16位短整数。 - 例如
htonl
表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。 - 如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回。
- 如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。
- 这些函数名很好记,
3.4 socket
编程接口
-
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);
-
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
结构体指针做为参数。 -
sockaddr
结构 -
sockaddr_in
结构虽然socket API的接口是
sockaddr
,但是我们真正在基于IPv4
编程时,使用的数据结构是sockaddr_in
;这个结构里主要有三部分信息:地址类型、端口号、IP地址。 -
in_addr
结构in_addr
结构用来表示一个IPv4
的IP地址,其实就是一个32位的整数。
-