【Linux】网络基础

一.初识协议

  • 协议:为了实现网络中的数据交换和通信,通信双方或多方共同遵循的一组规则、标准或约定。

1.协议分层

  • 协议分层:是将网络通信协议按照功能不同划分为多个层次,每个层次负责特定的任务,各层次相互协作共同完成网络通信。

在这里插入图片描述

  • 在这个例子中,我们的 “协议” 只有两层:语言层、通信设备层。
  • 但是实际的网络通信协议,设计的会更加复杂,需要分更多的层。
  • 但是通过上面的简单例子,我们是能理解,分层可以实现解耦合,让软件维护的成本更低。

高内聚低耦合:

  • 高内聚意味着模块内的各个部分联系紧密、职责单一,它们共同协作以完成一个明确的功能。
  • 低耦合表示模块之间的依赖程度尽可能低,一个模块的修改或变动不会对其他模块产生过多的影响。

网络协议栈:OSI、TCP/IP

2. OSI 七层模型

  • OSI(Open System Interconnection,开放系统互连)七层网络模型称为开放式系统互联参考模型,是一个逻辑上的定义和规范。
  • 把网络从逻辑上分为了 7 层,每一层都有相对应的物理设备,比如路由器,交换机,集线器。
  • OSI 七层模型是一种框架性的设计方法,其最主要的功能使就是帮助不同类型的主机实现数据传输。
  • 它的最大优点是将服务、接口和协议这三个概念明确地区分开来,概念清楚,理论也比较完整。通过七个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯。
  • 但是,它既复杂又不实用,所以我们按照 TCP/IP 四层模型来讲解。

在这里插入图片描述
在这里插入图片描述

  • 其实在网络角度,OSI 定的协议 7 层模型其实非常完善,但是在实际操作的过程中,会话层、表示层是不可能接入到操作系统中的,所以在工程实践中,最终落地的是 5 层协议。

3. TCP/IP 四(五)层模型

TCP/IP 是一组协议的代名词,它还包括许多协议,组成了 TCP/IP 协议簇,采用了 5 层的层级结构。

以层与层的角度:

  • 物理层:负责光/电信号的传递方式。比如现在以太网通用的网线(双绞线)、早期以太网采用的的同轴电缆(现在主要用于有线电视)、光纤,现在的 wifi 无线网使用电磁波等都属于物理层的概念。物理层的能力决定了最大传输速率、传输距离、抗干扰性等。集线器工作在物理层。
  • 数据链路层:负责设备之间的数据帧的传送和识别。例如网卡设备的驱动、帧同步(网线上检测到什么信号算作新帧的开始)、冲突检测(如果检测到冲突就自动重发)、数据差错校验等工作。有以太网、令牌环网、无线 LAN 等标准。交换机工作在数据链路层。
  • 网络层:负责地址管理和路由选择。例如在 IP 协议中, 通过 IP 地址来标识一台主机,并通过路由表的方式规划出两台主机之间的数据传输的线路(路由)。路由器工作在网路层。
  • 传输层:负责两台主机之间的数据传输。如传输控制协议(TCP),能够确保数据可靠的从源主机发送到目标主机。
  • 应用层:负责应用程序间沟通,如简单电子邮件传输(SMTP)、文件传输协议(FTP)、网络远程访问协议(Telnet)等。

在这里插入图片描述

物理层我们考虑的比较少,我们只考虑软件相关的内容。因此很多时候我们直接称为TCP/IP 四层模型。我们的网络编程主要就是针对应用层。

二.再识协议

1.什么是 TCP/IP 协议?

  • TCP/IP 协议的本质是一种解决网络通信的方案。
  • TCP/IP 协议能分层,前提是因为问题们本身能分层。

在这里插入图片描述

  • 所有的主机上面的操作系统可以不同,但是主机上的协议栈必须按照标准进行相同的实现,这就是为什么不同的主机,可以相互通信的秘密。
  • 网卡是低层硬件,数据链路层在驱动程序中,网络层和传输层被集成在内核中,应用层在操作系统上层由用户实现。
  • 传输层最著名的协议是TCP,网络层最著名的协议是IP,而传输层(TCP)和网络层(IP)必须实现在内核中,无论操作系统怎么不同,这两部分必须遵守协议,必须一样。
  • TCP和IP既然是核心,把这个协议整体统称为TCP/IP协议不过分吧!
  • 整个协议栈,涉及到硬件、驱动、操作系统、用户,这个协议一定需要IT各行各业进行支持和配合。

2.为何有 TCP/IP 协议?

  • 首先,即便是单机,你的计算机内部,其实都是存在协议的,比如:其他设备和内存通信,会有内存协议。其他设备和磁盘通信,会有磁盘相关的协议,比如:SATA,IDE,SCSI 等。只不过我们感知不到罢了。而且这些协议都在本地主机各自的硬件中,通信的成本、问题比较少。
  • 其次,网络通信最大的特点就是主机之间变远了。任何通信特征的变化,一定会带来新的问题,有问题就得解决问题,所以需要新的协议咯。
  • 为什么要有 TCP/IP 协议?本质就是通信主机距离变远了,需要解决一些网络通信存在的问题!

在这里插入图片描述

3.怎么实现 TCP/IP 协议?

  • 截止到目前,我们还没接触过任何协议,但是如何朴素的理解协议,我们已经可以试试了。
  • 操作系统源代码一般都是用 C/C++语言写的。
  • Windows 和 Linux 的网络协议代码 (结构体) 一定是一样的!

在这里插入图片描述

在这里插入图片描述

三.网络传输

1.网内传输

局域网(以太网为例)通信原理:

  • 两台主机在同一个局域网,是能够直接通信的!
  • 每台主机在局域网上,要有唯一的标识来保证主机的唯一性:MAC 地址。

1. MAC地址

  • MAC 地址用来识别数据链路层中相连的节点。
  • 长度为 48 比特位,即 6 个字节。一般用 16 进制数字加上冒号的形式来表示(例如:08:00:27:03:fb:19)
  • 在网卡出厂时就确定了,不能修改。MAC 地址通常是唯一的(虚拟机中的 MAC 地址不是真实的 MAC 地址,可能会冲突。也有些网卡支持用户配置 MAC 地址)

在这里插入图片描述

  • 以太网中的任何时刻,只允许一台机器向网络中发送数据,所有的主机都可以收到。
  • 如果有多台同时发送,会发生数据干扰,我们称之为数据碰撞,所有发送数据的主机要进行碰撞检测和碰撞避免。若检测到碰撞,主机先休眠一段时间,再重发数据。
  • 交换机能够隔离碰撞域,提高了网络的性能和效率。没有交换机的情况下,一个以太网就是一个碰撞域。
  • 局域网通信的过程中,主机将数据通过网卡,发送到数据链路层,通过 MAC 地址比对。如果数据是自己的,往上传到应用层;如果数据不是自己的,丢弃。
  • 这里可以试着从系统角度来理解局域网通信原理(以太网类似临界资源,碰撞检测和碰撞避免类似互斥机制,主机类似线程)

2.封装和解包

在网络传输的过程中,数据不是直接发送给对方主机的,而是先要自定向下将数据交付给下层协议(封装),最后由底层发送,然后由对方主机的底层来进行接受,在自底向上进行向上交付(解包)

在这里插入图片描述

下面我们明确一下概念:

在这里插入图片描述

  • 报头:对应协议层的结构体字段。
  • 除了报头,剩下的叫做有效载荷
  • 报文 = 报头 + 有效载荷

报头的共性:

  • 解包:报头和有效载荷分离的过程!与封装的过程相反!
  • 分用:报头中内部,必须包含一个字段,由什么协议发给当前层,未来要将有效载荷交给哪一个协议。

不同层的完整报文的叫法:

  • 不同的协议层对数据包有不同的称谓。应用层:请求与相应;传输层:报文段(TCP协议),用户数据报(UDP协议);网络层:IP数据报;数据链路层:帧;物理层:比特流。
  • 应用层数据通过协议栈发到网络上时,每层协议都要加上一个数据首部,称为封装。
  • 首部信息中包含了一些类似于首部有多长,载荷有多长,上层协议是什么等信息。
  • 数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部,根据首部中的 “上层协议字段” 将数据交给对应的上层协议处理。

问题:

  • 为什么要封装?首先发消息必须先发给网卡,网卡是硬件,必须调系统调用,所以会贯穿整个操作系统!
  • 收数据时,必须是网卡先收到数据,主机如何知道网卡上存在数据?发送中断!

下图为数据封装的过程:

在这里插入图片描述

下图为数据分用的过程:

在这里插入图片描述

在这里插入图片描述

2.跨网传输

以太网和令牌环网通信:

  • 两台主机在不同局域网上,需要通过路由器进行通信的!
  • 每台主机在不同局域网上,要有唯一的标识来保证主机的唯一性:IP 地址。

1. IP地址

IP 协议有两个版本,IPv4 和 IPv6。我们整个的课程,凡是提到 IP 协议,没有特殊说明的,默认都是指 IPv4。

  • IP 地址是在 IP 协议中,用来标识网络中不同主机的地址。
  • 对于 IPv4 来说,IP 地址是一个 4 字节,32 位的整数。
  • 我们通常也使用 “点分十进制” 的字符串表示 IP 地址,例如 192.168.0.1 用点分割的每一个数字表示一个字节,范围是 0 ~ 255。

跨网段的主机的数据传输,数据从一台计算机到另一台计算机传输过程中要经过一个或多个路由器。

下面是一张示意图:

在这里插入图片描述

在这里插入图片描述

  • 每一个主机的网络层都存在路由功能。
  • 为什么要去目标主机,先要走路由器:同一个子网内,IP 地址的前缀一样,数据经过网络层,发现源 IP 地址和目的 IP 地址的前缀不一致,说明该数据不是发给所在的局域网的主机,而路由器是子网的出口

结合封装与解包,体现路由器解包和重新封装的特点:

在这里插入图片描述

对比 IP 地址和 Mac 地址的区别

  • IP 地址在整个路由过程中几乎不变,Mac 地址一直在变。
  • 目的 IP 是一种长远目标,Mac 是下一阶段目标,目的 IP 是路径选择的重要依据,MAC 地址是局域网转发的重要依据。
  • 在网络层,各个主机和各个路由器拿到的 IP 数据报是一样的!差异在于,数据每经过一个路由器会解包旧 MAC 地址、封装新的 MAC 地址,适配另一个子网!

提炼 IP 网络的意义和网络通信的宏观流程:

在这里插入图片描述

  • IP 网络层存在的意义:提供网络虚拟层,让世界的所有网络都是 IP 网络,屏蔽最底层网络(以太网、令牌环网、无线WLAN)的差异。

四. Socket 编程预备

1.源IP地址和目的IP地址

IP 在网络中,用来标识主机的唯一性

  • 但是这里要思考一个问题:数据传输到主机是目的吗?不是的。因为数据是给人用的。比如:聊天是人在聊天,下载是人在下载,浏览网页是人在浏览!
  • 但是人是怎么看到聊天信息的呢?怎么执行下载任务呢?怎么浏览网页信息呢?通过启动的 qq,迅雷,浏览器。而启动的 qq,迅雷,浏览器都是进程。换句话说,进程是人在系统中的代表,只要把数据给进程,人就相当于就拿到了数据。
  • 所以:数据传输到主机不是目的,而是手段。到达主机内部,在交给主机内的进程,才是目的。
  • 但是系统中,同时会存在非常多的进程,数据通过 IP 地址到达目标主机之后,怎么转发给目标进程?这就要在网络的背景下,在系统中,标识主机的唯一性。

在这里插入图片描述

2.端口号

端口号是传输层协议的内容:

  • 端口号是一个 2 字节 16 比特位的整数。
  • 端口号用来标识一个进程,告诉操作系统,当前的这个数据要交给哪一个进程来处理。
  • IP 地址 + 端口号:标识网络上的某一台主机的某一个进程。
  • 一个端口号只能被一个进程占用。

在这里插入图片描述

1.端口号范围划分

  • 0 ~ 1023:知名端口号;HTTP,FTP,SSH 等这些广为使用的应用层协议,他们的端口号都是固定的。
  • 1024 ~ 65535:操作系统动态分配的端口号;客户端程序的端口号,就是由操作系统从这个范围分配的。

2.端口号和进程ID

  • 我们之前在学习系统编程的时候,学习了 pid 表示唯一一个进程。此处我们的端口号也是唯一表示一个进程。那么这两者之间是怎样的关系?
  • 一个进程可以绑定多个端口号,但是一个端口号不能被多个进程绑定。进程 ID 属于系统概念,技术上也具有唯一性,确实可以用来标识唯一的一个进程,但是这样做,会让系统进程管理和网络强耦合,实际设计的时候,并没有选择这样做。

3.源端口号和目的端口号

传输层协议 (TCP 和 UDP) 的数据段中有两个端口号,分别叫做源端口号和目的端口号,就是在描述 “数据是谁发的,要发给谁”。

4.理解 socket

总结:IP 地址用来标识互联网中唯一的一台主机,port 用来标识该主机上唯一的一个网络进程:

  • IP + Port 就能表示互联网中唯一的一个进程。
  • 网络通信的本质:两个互联网进程代表人来进行通信,{srcIp,srcPort,dstIp,dstPort} 这样的 4 元组就能标识互联网中唯二的两个进程。
  • 网络通信的本质:进程间通信,公共资源就是网络!
  • 我们把 ip+port 叫做套接字 socket

3.传输层经典协议

如果我们了解了系统,也了解了网络协议栈,我们就会清楚,传输层是属于内核的,那么我们要通过网络协议栈进行通信,必定调用的是传输层提供的系统调用,来进行的网络通信。

在这里插入图片描述

1.TCP协议

传输控制协议TCP:传输层协议、有连接、可靠传输、面向字节流。

2.UDP协议

用户数据报协议UDP:传输层协议、无连接、不可靠传输、面向数据报。

4.网络字节序

我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分,磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分,网络数据流同样有大端小端之分。那么如何定义网络数据流的地址呢?

  • 小端:低地址低位,高地址高位;大端:低地址高位,高地址低位。
  • 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出。
  • 接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存。
  • 网络数据流的地址规定:先发出的数据是低地址,后发出的数据是高地址
  • TCP/IP 协议规定,网络数据流应采用大端字节序,即低地址高字节。
  • 不管这台主机是大端机还是小端机,都会按照这个 TCP/IP 规定的网络字节序来发送/接收数据。
  • 如果当前发送主机是小端,就需要先将数据转成大端;否则就忽略,直接发送即可。

在这里插入图片描述

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

在这里插入图片描述

  • h 表示 host;n 表示 network;l 表示 32 位长整数;s 表示 16 位短整数。
  • 例如 htonl 表示将 32 位的长整数从主机字节序转换为网络字节序,例如将 IP 地址转换后准备发送。
  • 如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回。
  • 如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。

网络规定:所有发送到网络上的数据,都必须是大端的!

5. socket 编程接口

1. socket 常见 API

// 创建 socket
原型: int socket(int domain, int type, int protocol);
参数domain: AF_INET表示网络通信, AF_UNIX表示本地通信
参数type: SOCK_STREAM表示TCP, SOCK_DGRAM表示UDP
参数protocol: 设置为0
返回值: 成功返回文件描述符fd, 失败返回-1

// 绑定网络信息: IP + 端口号
原型: int bind(int socket, const struct sockaddr *address, socklen_t address_len);
参数address: sockaddr_in表示网络通信, sockaddr_un表示本地通信(需要强转)

// 开始监听 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);

2. sockaddr 结构

socket编程的种类:

  • 网络socket(本地+网络)
  • 本地socket(unix域间socket)
  • 原始socket

socket API 是一层抽象的网络编程接口,适用于各种底层网络协议,如 IPv4、IPv6,以及后面要讲的 UNIX Domain Socket。然而,各种网络协议的地址格式并不相同,操作系统需要为各种socket编程提供系统调用,为了适用各种socket编程,设计了3中结构体:

在这里插入图片描述
在这里插入图片描述

  • 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 结构体指针做为参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值