解码网络编程基础

news/2025/11/23 17:26:39/文章来源:https://www.cnblogs.com/YouEmbedded/p/19234587

进程间通信方式

基础概念

程序是数据和指令的集合,运行时成为进程,操作系统会为其分配资源并记录参数。同一主机内进程通信可通过管道、信号、消息队列、信号量集、共享内存实现,这些方式依赖主机本地系统资源,无法跨主机使用。

程序是静态的 “数据 + 指令” 集合,进程是程序加载运行后的动态实例 —— 操作系统会为进程分配 CPU、内存等资源,还会创建进程控制块(PCB)记录关键参数。

同一主机内,进程可通过管道、信号、消息队列等本地 IPC 方式通信,但这些方式依赖本地内核资源,不同主机的内核无法互通,因此不能跨主机使用

若要实现跨主机进程通信(比如本地 APP 连云端服务器),就需要网络打破主机资源隔离 —— 通过网线、光纤等物理链路,配合 TCP/IP 等统一协议,建立数据传输通道;而 Socket(套接字)正是基于网络协议的跨主机 IPC 接口,能让不同主机的进程通过网络交互数据。

Socket(套接字)

Socket 是 Linux 系统中实现跨主机进程双向通信的特殊接口,对应套接字文件类型,是互联网中主机应用进程通信的核心方式。其工作依赖网络协议(如同插座需匹配线路),采用 C/S(客户端 / 服务器)架构,支持多客户端并发访问同一服务器或一对一通信。

image

/*** Socket创建函数,用于初始化跨主机通信接口* @brief 建立客户端与服务器的通信端点,指定通信协议类型* @param domain 协议族(如AF_INET对应IPv4,AF_INET6对应IPv6),定义通信地址格式* @param type 套接字类型(SOCK_STREAM为TCP面向连接,SOCK_DGRAM为UDP无连接)* @param protocol 具体协议(0表示默认匹配type对应的协议,如TCP对应IPPROTO_TCP)* @return int 成功返回套接字文件描述符(非负整数),失败返回-1* @note 跨主机通信必须使用Socket,同一主机的进程通信方式因不共享系统资源无法跨主机使用*       套接字文件是Linux七种文件类型之一,专门用于不同主机进程间的数据传输*       C/S架构下,服务器需先绑定端口并监听,客户端通过IP和端口连接服务器*/
int socket(int domain, int type, int protocol);

IP 地址

核心作用

IP 地址是互联网中主机或设备的唯一标识符,由 IP 协议分配,格式统一,确保主机间精准通信,避免数据误发。

image

起源与协议标准

互联网源于冷战时期美国 ARPA(高级研究计划署)的研究,采用分布式模型可避免战争导致的网络瘫痪。IP 协议及其他网络协议标准可通过 RFC 官网(https://www.rfc-editor.org/)下载,RFC(征求意见稿)由 IETF(互联网工程任务组)发布,包含互联网技术和组织核心资料。

image

格式与表示

IP 协议规定 IPv4 地址为 32 位,分为 4 个 8 位字段,每个字段用十进制表示(0~255),字段间用英文句号分隔,称为 “点分十进制”,如 192.168.1.1。

分类与范围

IP 地址分为 A、B、C、D、E 五类,其中 A、B、C 类用于标识主机,D 类用于多播,E 类预留。

  • A 类地址:最高位为 0,网络编号 7 位,本地地址 24 位。理论范围 0.0.0.0~127.255.255.255,因网络编号 0 和 127 保留(0 表示本网络,127 为环回地址),实际可用范围 1.0.0.0~126.255.255.255,支持 126 个网络,每个网络理论支持 2²⁴台主机,扣除本地地址全 0(网络地址)和全 1(广播地址),实际可用 2²⁴-2 台。

    image

  • B 类地址:最高两位为 10,网络编号 14 位,本地地址 16 位。范围 128.0.0.0~191.255.255.255,支持 16384 个网络,每个网络理论 65536 台主机,实际可用 65534 台(扣除网络地址和广播地址)。

    image

  • C 类地址:最高三位为 110,网络编号 21 位,本地地址 8 位。范围 192.0.0.0~223.255.255.255,支持 2097152 个网络,每个网络理论 256 台主机,实际可用 254 台。

    image

  • D 类地址:范围 224.0.0.0~239.255.255.255,用于 IP 多播;

    E 类地址:240.0.0.0~255.255.255.255,预留使用,均无本地地址,不标识主机。

特殊地址

环回地址:127.xxx.xxx.xxx,用于主机自身测试,如 127.0.0.1,通过 ping 命令可验证网卡和 IP 协议是否正常。

/*** ping命令,用于测试主机网络连通性* @brief 向目标IP发送ICMP请求包,接收响应判断网络状态* @param target_ip 目标IP地址(如127.0.0.1为本地环回地址)* @return int 0表示连通正常,非0表示连通异常* @note 测试127.0.0.1成功,说明主机网卡和IP协议工作正常*       输出中"0% packet loss"表示无数据包丢失,通信正常*       响应时间(time字段)反映通信延迟,越小越好*/
ping 127.0.0.1
  • 网络地址:本地地址全 0,仅标识网络,如 5.0.0.0,用于路由器记录网段。
  • 广播地址:本地地址全 1,用于向网段内所有主机发送数据,如 5.255.255.255。

IPv4 与 IPv6 对比

  • IPv4:32 位地址,约 42 亿个可用地址,地址空间不足。
  • IPv6:128 位地址,约 340 万亿亿亿亿个可用地址,解决地址枯竭问题,功能更完善。
  • 配置选择:当前 IPv4 仍广泛使用,IPv6 逐步普及,网络支持时优先选择 IPv6,兼容场景可同时配置两者。

子网掩码

作用

用于从 IP 地址中提取网络编号,判断两台主机是否处于同一网络(网络编号相同则为同一网络)。

默认子网掩码

  • A 类地址:255.0.0.0(对应网络编号 8 位)
  • B 类地址:255.255.0.0(对应网络编号 16 位)
  • C 类地址:255.255.255.0(对应网络编号 24 位)

CIDR 无分类地址方案

格式为 a.b.c.d/x,x 表示网络编号位数(0~32),替代传统分类地址,简化 IP 管理。如 192.168.5.120/24,对应子网掩码 255.255.255.0,网络编号 24 位,主机编号 8 位。

/*** 计算IP地址对应的网络编号* @brief 通过IP地址与子网掩码的位与运算,提取网络编号* @param ip IP地址(32位无符号整数,点分十进制转换后)* @param subnet_mask 子网掩码(32位无符号整数,点分十进制转换后)* @return uint32_t 网络编号(32位无符号整数)* @note 位与运算规则:对应位均为1结果为1,否则为0*       例:IP=192.168.5.120(0xC0A80578),掩码=255.255.255.0(0xFFFFFF00),结果=0xC0A80500(192.168.5.0)*       网络编号相同的主机可直接通信,不同则需路由器转发*/
uint32_t get_network_id(uint32_t ip, uint32_t subnet_mask) {return ip & subnet_mask;
}

网络模型

OSI 七层模型(概念性模型)

从下到上依次为:

image

TCP/IP 四层模型(实践类模型,当前互联网主流)

image

数据传输流程

数据从发送端应用层出发,每经过一层添加对应首部(封包),到达接收端后逐层拆除首部(拆包),最终传递到应用层,实现原始数据传输。
image

各层核心内容

物理层

  • 传输介质:架空明线、电缆、光纤、无线信道等(不属于物理层,是传输载体)

  • 设备:集线器(Hub,广播式发送数据)、中继器(扩大传输距离,重发信号)

    image

  • 传输速率:

    • 波特率:单位时间内传输的码元个数,单位 baud
    • 比特率:单位时间内传输的二进制码元个数,单位 bit/s,二进制码元时与波特率相等
  • 四大特性:机械特性(接口形状、尺寸)、电气特性(电压范围)、功能特性(信号线用途)、规程特性(事件时序)

数据链路层

  • 核心功能:将物理层比特流转为帧,实现差错控制,提升传输可靠性

  • 帧结构:包含首部(起始 / 结束标识、地址等)、数据部分、尾部(校验信息),如 PPP 协议帧

  • 最大传输单元(MTU):各网络类型对帧的最大长度限制,如以太网 MTU 为 1500 字节,超过需分片

  • 设备:交换机(多端口网桥,基于 MAC 地址转发帧,全双工通信)、网桥(连接不同局域网)

    image

/*** 数据链路层帧封装函数* @brief 将网络层数据报封装为数据链路层帧,添加帧首部和尾部* @param frame 输出参数,存储封装后的帧数据* @param data 网络层数据报内容* @param data_len 数据报长度(字节)* @param src_mac 源MAC地址(6字节),标识发送端设备* @param dest_mac 目的MAC地址(6字节),标识接收端设备* @return int 封装后的帧长度(字节),失败返回-1* @note 帧首部包含起始标志(如PPP协议的0x7E)、MAC地址等,尾部包含FCS校验字段*       若data_len超过MTU,需先进行分片处理,再分别封装*       MAC地址是设备物理地址,全球唯一,用于同一网络内设备识别*/
int frame_encapsulate(uint8_t *frame, const uint8_t *data, uint32_t data_len, const uint8_t *src_mac, const uint8_t *dest_mac) {// 帧封装逻辑实现,此处省略具体代码return frame_len;
}

网络层

  • 核心功能:路由(路径规划)和转发(数据报传递),实现跨网络通信

  • 核心协议:IP 协议,负责数据报传输,定义数据报格式,支持分片与重组

    • 分片与重组

      由于网络中不同链路的最大传输单元(MTU,Maximum Transmission Unit)可能会不同,如果当数据包的大小超过某个链路的MTU(比如以太网的MTU最大为1500字节)时,IP协议会将数据包进行分片,以适应数据链路的最大传输单元。接收方的IP协议根据数据报首部中的标识和片偏移字段将分片的数据包进行重组,可以再次得到原始的数据包。

  • IP 数据报格式:包含版本(IPv4/IPv6)、首部长度、总长度、源地址、目的地址等字段,首部最小 20 字节(无可选字段),最大 60 字节(可选字段最多 40 字节)

    image

  • 设备:路由器,连接多个网络,根据路由表转发数据报,支持不同协议转换

    image

    image

传输层

  • 核心功能:为应用进程提供端到端通信服务,解决网络层不可靠传输问题(丢包、失序等)

    image

  • 核心协议:

    • TCP(传输控制协议):可靠、面向连接,支持流量控制和拥塞控制
    • UDP(用户数据报协议):不可靠、无连接,传输效率高
  • 端口号:标识主机内应用进程,16 位整数,范围 0~65535

    • 保留端口(0~1023):用于熟知服务(如 21 对应 FTP,23 对应 Telnet)
    • 注册端口(1024~49151):需向 IANA 登记,避免冲突
    • 动态端口(49152~65535):临时分配,通信结束释放
/*** TCP连接建立函数(三次握手)* @brief 客户端向服务器发起TCP连接,完成三次握手过程* @param sockfd 套接字文件描述符(已通过socket函数创建)* @param server_addr 服务器地址结构(包含IP和端口号)* @param addr_len 地址结构长度* @return int 成功返回0,失败返回-1* @note 三次握手流程:客户端发SYN→服务器回SYN+ACK→客户端发ACK*       连接建立后,双方可进行可靠数据传输,TCP会确认、重传丢失数据包*       端口号用于标识服务器端对应服务进程(如80端口对应HTTP服务)*/
int tcp_connect(int sockfd, const struct sockaddr *server_addr, socklen_t addr_len) {return connect(sockfd, server_addr, addr_len);
}

会话层

负责通信会话的创建、维护和终止,支持会话中断后的重连,协调双方通信节奏,避免拥塞时会话中断。

表示层

  • 数据转换:将应用层字符 / 数字转为二进制数据(编码),接收端反向转换(解码)
  • 数据压缩:减少数据体积,提升传输效率,适用于实时音视频传输
  • 数据加密:保障数据传输安全,防止信息泄露

应用层

直接对接应用程序,提供具体网络服务,如电子邮件、网页浏览等,常见应用层协议有 HTTP(网页服务)、FTP(文件传输)、SMTP(邮件发送)等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/974066.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++的3种继承方式

C++的3种继承方式 在 C++ 中,继承方式(public、protected、private)决定了基类成员在派生类中的访问权限,以及派生类对象对基类成员的访问权限。正确选择继承方式是实现封装、复用和多态的关键。以下是三种继承方式…

1082. Read Number in Chinese (25)

1082. Read Number in Chinese (25)#include <iostream> #include <string.h>using namespace std;int first = 1;void setfirst() {if(first == 1){first = 0;}else{printf(" ");} }int main()…

1081. Rational Sum (20)

1081. Rational Sum (20)#include <iostream>using namespace std;long long getsame(long long a, long long b) {if(b != 0){return getsame(b, a % b);}else{return a;} }void simplify(long long &a, lo…

1067. Sort with Swap(0) (25)

1067. Sort with Swap(0) (25)#include <iostream>using namespace std;int index[100010], num[100010];int main() {int n;scanf("%d", &n);int i, count = 0;for(i = 0; i < n; i++){scanf(…

1066. Root of AVL Tree (25)

1066. Root of AVL Tree (25)#include <iostream> #include <stdlib.h>using namespace std;typedef struct node {int key, bf;struct node *lchild, *rchild; }*bnode;void rrotate(bnode *root) {bnode…

1070. Mooncake (25)

1070. Mooncake (25)#include <iostream> #include <algorithm>using namespace std;struct node {double amounts, prices, perprice; }mooncakes[1010];int cmp(node n1, node n2) {return n1.perprice …

1069. The Black Hole of Numbers (20)

1069. The Black Hole of Numbers (20)#include <iostream> #include <string.h> #include <algorithm>using namespace std;int cmp(char a, char b) {return a > b; }int main() {int num[2];s…

1050. String Subtraction (20)

1050. String Subtraction (20)#include <iostream> #include <string.h>using namespace std;int flag[130]; char s[2][10010];int main() {int i, len[2];for(i = 0; i <= 1; i++){gets(s[i]);len[i…

1049. Counting Ones (30)

1049. Counting Ones (30)#include <iostream>using namespace std;int main() {int n;scanf("%d", &n);int low, mid, high, d = 1, res = 0;while(n >= d){high = n / (d * 10);mid = (n - h…

1045. Favorite Color Stripe (30)

1045. Favorite Color Stripe (30)#include <iostream>using namespace std;int fav[210], ori[10010], res[210][10010];int getmax(int a, int b) {if(a > b){return a;}else{return b;} }int main() {int …

1048. Find Coins (25)

1048. Find Coins (25)#include <iostream> #include <algorithm>using namespace std;int c[510], num[100010];int main() {int n, m;scanf("%d%d", &n, &m);int i;for(i = 1; i <…

1052. Linked List Sorting (25)

1052. Linked List Sorting (25)#include <iostream> #include <algorithm> #include <vector>using namespace std;struct node {int address, key, next; }nod[100000];int cmp(node n1, node n2)…

1051. Pop Sequence (25)

1051. Pop Sequence (25)#include <iostream> #include <stack>using namespace std;int main() {int m, n, k;scanf("%d%d%d", &m, &n, &k);int i, num[1010], j, index, flag, be…

卡塔兰long long

1.mod 我们用递推式用加法避免除和mod include <bits/stdc++.h> using namespace std; long long dp[105]; long long f(int x) { if(dp[x]!=-1) return dp[x]; dp[x]=0;//归0 for(int i=0;i<x;i++) { dp[x]=…

1038. Recover the Smallest Number (30)

1038. Recover the Smallest Number (30)#include <iostream> #include <string.h> #include <string> #include <algorithm> #include <vector>using namespace std;int cmp(string a,…

1037. Magic Coupon (25)

1037. Magic Coupon (25)#include <iostream> #include <vector> #include <algorithm>using namespace std;int main() {int nc;scanf("%d", &nc);int i;vector<long long> v[…

1040. Longest Symmetric String (25)

1040. Longest Symmetric String (25)#include <iostream> #include <string.h>using namespace std;int main() {char s[1010];gets(s);int len = strlen(s), i, count, res = 0, j, k;for(i = 0; i <…

1029. Median (25)

1029. Median (25)#include <iostream> #include <vector> #include <algorithm>using namespace std;int main() {int n;scanf("%d", &n);int i;long int num;vector<long int>…

1039. Course List for Student (25)

1039. Course List for Student (25)#include <iostream> #include <vector> #include <algorithm>using namespace std;vector<int> v[270000];int getbigindex(char s[]) {return (s[0] - A…

1033. To Fill or Not to Fill (25)

1033. To Fill or Not to Fill (25)#include <iostream> #include <algorithm>using namespace std;struct node {double dis, p; }stations[510];int cmp(node n1, node n2) {return n1.dis < n2.dis;…