网络基础2

目录

跨网络传输流程

[网络中的地址管理 - 认识 IP 地址](#网络中的地址管理 - 认识 IP 地址)

跨网络传输

报文信息的跨网络发送

IP地址的转化

认识端口号

端口号范围划分

源端口号和目的端口号

[认识 TCP / UDP协议](#认识 TCP / UDP协议)

[理解 socket](#理解 socket)

网络字节序

[socket 编程接口](#socket 编程接口)

[sockaddr 结构](#sockaddr 结构)


我们继续来学习网络基础

跨网络传输流程

网络中的地址管理 - 认识 IP 地址

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

IP 地址是在 IP 协议中,用来标识网络中不同主机的地址,我们通常也使用 "点分十进制" 的字符串表示 IP 地址,例如 192.168.0.1 ; 用点 分割的每一个数字表示一个字节, 范围是 0 - 255

上图inet这里就是我这台主机的ip地址,我们使用ifconfig查到的一般都是私有ip,不是公网ip,如果 ifconfig 显示公网IP,通常意味着你的设备直接暴露在互联网上,需特别注意安全防护!

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

IP地址(特指公网IP)可以在全球互联网范围内唯一标识一台主机,mac地址是在局域网标识一台主机的唯一性,二者的本质区别就是,一个报文从发送到被接受时,其携带的源ip地址和目的ip地址一般是不变的,假设这个报文需要通过主机或者路由器中转,那mac地址会由于中转的作用而发生改变,每经过一个路由器或者主机其源mac地址和目的地址就会发生改变,一般经过路由器时会重新分配mac帧,此时变成跨网段通信了,mac地址的格式就发生了比较大的改变,这时这个mac地址就不属于原本的局域网的了。所以一般而言,mac地址只在局域网中有效!!!

在一个局域网内,报文每经过一个主机(不是目标主机)就将这个主机的网卡的mac地址作为新的源mac地址,然后把其要去到的下一个主机的网卡mac地址作为目标的mac地址。经过路由器时mac地址由路由器重新分配。

跨网络传输

跨网络传输一般直接使用ip地址,需要使用路由器这个硬件进行跨网络的传输,跨网段的主机的数据传输,数据从一台计算机到另一台计算机传输过程中要经过一个或 多个路由器。由图可以看出路由器有自己的ip地址,并且可以被左右两边不同网络的主机识别,一个以太网的程序进入路由器中,然后经由路由器传入一个使用令牌环驱动的网络,反之亦如此,这里主要是想体现不同技术实现的网络可以进行传输,所以路由器肯定有这两种网络程序兼容的接口,一定兼容这两种网络,并且这两种网络的网络层协议一定是一样的,不然不能通信。

令牌环网(Token Ring) 是一种早期的局域网(LAN)技术,由IBM在1980年代推出,遵循 IEEE 802.5 标准。它的核心特点是 通过"令牌"(Token)控制网络访问权限 ,确保数据有序传输,避免冲突(与以太网的CSMA/CD机制不同)。令牌(Token) 是一个特殊的短帧,在网络中单向循环传递只有拿到令牌的设备才能发送数据,发送完成后必须释放令牌给下一台设备。效率一看就是比较低的,图上的令牌环里面有很多的主机。

以太网(Ethernet) 是现代局域网(LAN)和互联网的核心通信技术 ,由Xerox、Intel和DEC在1970年代开发,现由 IEEE 802.3 标准规范。它的核心特点是 使用"竞争式"访问机制(CSMA/CD) 实现设备间的数据传输,支持从家庭网络到数据中心的广泛应用。

报文信息的跨网络发送

一个报文通过封装报头的方式传输到网卡准备发送到别的主机,这时源主机发现目标的ip地址和源ip地址不在同一个网段就会直接交给路由器,然后路由器连接着两个不同的网络,这时会进行判断是不是另一个网络的,如果是的话就根据修改报文的mac帧使其和另一个网络的mac地址格式一致,然后交给另一个网络的目标主机,如果路由器发现还是和另一个网络不一致,就会继续路由,交给下一个路由器,如果这个目标ip地址是属于和源ip地址是同一个网段的,就直接交给同一个网段的目标主机,这时传输使用的是mac地址和ip地址以及路由器无关了,反正你记住在同一个网段内传输使用的是mac地址,在不同网段之间传输使用的是ip地址,也仅仅是跨网络的那一刻使用的是ip地址进行判断的。

在ip网络中一切皆ip,同一个网段下的所有主机的ip地址都是由这个网段里面的路由器分配的。

用户主机可以和路由器进行传输,说明他们的网络层协议是相同的,说明路由器也是分层的。可以看到路由器内部有网络层和数据链路程

IP 网络层存在的意义:提供网络虚拟层,让世界的所有网络都是 IP 网络,屏蔽 最底层网络的差异。

IP地址的转化

IP地址有点分十进制的标识方法,这种方法具有很强的可读性,然而这种一长串字符串的表示方法在网络通信中不使用,在网络通信中IP地址被表示为4个以点分割的字符相当于char.char.char.char,每个字节对应一个 点分十进制(Dotted Decimal Notation) 的数值(如 192.168.1.1)。unsigned char 可以存储 0~255 的数值,正好适合存储IP地址的每个部分(0~255)。这种4字节的ip和之前的一长串的字符串ip是可以互相转换的。

怎么转呢,有函数可以进行帮助转化,我们后面实战的时候再说,原理就是,IP的结构可以是一个结构体吧,吧其内部装着的4个char类型的字符都提取出来进行to_string转换成字符串然后用.连接,之间+.,这样就拼接成点分十进制的了,反过来也是同理。

认识端口号

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

数据传输到主机不是目的,而是手段。到达主机内部,在交给主机内的进程, 才是目的。交给主机内的进程就需要标识主机的唯一性,这些端口号都是报文传输时已经知道了的或者人工设置进去的,那为什么标识唯一进程不使用进程的pid呢,这样不就和进程的管理/调度强耦合了吗,网络部分为了不被操作系统内核影响就新增了端口号。怎么通过端口号找到进程的,这里相当于使用了哈希表的映射,将下标定义为端口号,然后内容介绍进程的pcb,这样只需要查找端口号哈希表然后映射着找到进程pcb,再进而找到所对应的进程,然后通过文件描述符找到网络。一切皆文件,在Linux的操作系统看来网络就是文件。

端口号范围划分

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

所以一般设置端口号不能设置这些知名的端口号,防止访问冲突。

另外, 一个进程可以绑定多个端口号; 但是一个端口号不能被多个进程绑定。

源端口号和目的端口号

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

认识 TCP / UDP协议

此处我们先对 TCP(Transmission Control Protocol 传输控制协议)有一个直观的认识,后面我们再详细讨论 TCP 的一些细节问题。

此处我们也是对 UDP(User Datagram Protocol 用户数据报协议)有一个直观的认识,后 面再详细讨论。

面向字节流就是数据像水流一样连续,发送方写入的多次数据可能被接收方一次性读取(或反之)。例如:发送方分3次发送 "Hello""World""!",接收方可能一次性收到 "HelloWorld!"

面向数据报就是每次发送的数据是一个独立单元,接收方必须按完整单元读取,例如:发送方分3次发送 "Hello""World""!",接收方会收到3次独立的数据包。

UDP的不可靠传输是其特点,不是缺点,是低延迟、能容忍丢包的传输方式。

理解 socket

综上,IP 地址用来标识互联网中唯一的一台主机,port 用来标识该主机上唯一的 一个网络进程,网络的本质就是进程间的通信,我们把 ip+port 叫做套接字 socket,我们可以通过创建套接字发方式进行本地或者跨网络通信。套接字是通用通信接口。

网络字节序

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

发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出,接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从 低到高的顺序保存,那接收的主机和发生的主机如果大小端不一数据不就发送和读取不一致了吗,所以TCP/IP 协议规定,网络数据流应采用大端字节序,即低地址高字节,介绍发送到网络中的数据必须才用大端字节序保证数据的接发的一致性,在主机中的数据随意,该转小端存储转小端,发送方该转大端转大端。

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

socket 编程接口

sockaddr 结构

我们这里不做接口的介绍,仅仅解释sockaddr是什么。

socket编程可以实现局域网通信以及跨网络通信,所以socket的种类分为网络socket,本地socket,和原始socket,本地socket就是unix域间通信,就是管道。

我们可以看到上面这些套接字编程接口函数都有一个参数是struct sockaddr*,struct sockaddr是一个"地址结构体 "!它的作用是告诉内核:"我的这个套接字要绑定/连接到哪里 。",所以其结构体内部会有这个套接字所对应的端口号和ip地址,然后struct sockaddr_in是是用于 IPv4 网络编程 的结构体,表示一个网络套接字的地址信息(IP + 端口),in就是inet的简写,struct sockaddr_un是表示本地套接字的地址信息,un就是unix的接口。

这些结构体里面都必须要有端口号,ip地址以及一个8字节的填充。那么多种socket需要通信,操作系统需要提供每种套接字的系统调用,所以OS将这些socket接口统一了,到时候统一传入struct sockaddr*,那怎么区分是那种socket,所以实际传入的是原本socket的自己强制性转换成struct sockaddr*的版本,怎么强制性转换的呢,这些struct sockaddr_in/struct sockaddr_un会在里面提供一个16位地址类型网络socket的就是AF_INET,本地socket就是AF_UNIX。这些都是宏,相当于用原本的socket转换成了统一的版本,然后回根据这些16位的宏进行判断转换的是什么,再执行对应的通信策略。

IPv4、IPv6 地址类型分别定义为常数 AF_INET、AF_INET6. 这样,只要取得某 种 sockaddr 结构体的首地址,不需要知道具体是哪种类型的 sockaddr 结构体,就可 以根据地址类型字段确定结构体中的内容。

最后,这样转换的操作使得不同的struct变成同一个struct,然后执行不同的通信效果,这不就是多态吗,struct sockaddr不是套接字,而是套接字要绑定或连接的"地址"信息,就是创建套接字是需要填充struct sockaddr里面的ip,端口号等信息的。

Socket 既是"IP + 端口"的组合,也是文件描述符,但这两者描述的是 Socket 的不同层面。

相关推荐
facaixxx202427 分钟前
什么是巨型帧Jumbo Frames?云服务器开启巨型帧有什么用?
运维·服务器
巨可爱熊3 小时前
高并发内存池(定长内存池基础)
linux·运维·服务器·c++·算法
yangang1855 小时前
linuxbash原理
linux·运维·服务器
一一Null6 小时前
关于手机取证中逻辑采集与系统备份的差异
服务器·网络·智能手机
码农新猿类6 小时前
服务器本地搭建
linux·网络·c++
yangshuo12816 小时前
如何在服务器上搭建mail服务器邮件服务器
运维·服务器
独行soc7 小时前
2025年常见渗透测试面试题-红队面试宝典下(题目+回答)
linux·运维·服务器·前端·面试·职场和发展·csrf
SlientICE7 小时前
TCP是什么?不需要!使用ESP32网络层直接通信!
网络·单片机·网络协议·tcp/ip
小丁爱养花7 小时前
驾驭 Linux 云: JavaWeb 项目安全部署
java·linux·运维·服务器·spring boot·后端·spring
小李超勇的..9 小时前
SOME/IP
网络·网络协议·tcp/ip