当前位置: 首页 > news >正文

Linux学习-通信(网络通信)


一、Linux 应用软件编程 - 网络编程 整体框架

涵盖 文件操作、多任务并发 基础,核心聚焦 “不同主机进程间通信”,解决 物理网络连通 + 软件进程互通 问题。
在这里插入图片描述

二、网络通信核心概念

1. 网络标识体系
标识类型作用特点
IP 地址软件地址,标识主机分公网(直连互联网)、私网(局域网内)
MAC 地址硬件地址,固定标识设备全球唯一
端口号标识主机内不同网络进程16 位整数(0~65535)
2. 网络协议与分层模型
  • OSI 七层模型(理论参考):从应用层到物理层定义通信标准,核心关注 传输层(TCP/UDP)、网络层(IP 路由)
  • TCP/IP 五层模型详细说明表
层级(从下到上)核心功能常见协议典型设备关键技术/标识应用场景示例
1. 物理层定义物理设备标准,处理物理介质上的原始比特流传输,规定电气、机械、接口特性无独立协议(依赖硬件标准)集线器、中继器、网线、光纤、无线AP比特流、物理接口(RJ-45、LC)以太网物理连接、Wi-Fi信号传输
2. 数据链路层封装原始比特流为“帧”,实现相邻节点间可靠传输,处理帧同步、差错控制、MAC寻址以太网协议(Ethernet)、PPP(点到点协议)、HDLC(高级数据链路控制协议)交换机、网卡帧、MAC地址(设备硬件地址)局域网内设备间数据转发
3. 网络层实现跨网络的“数据包”路由与转发,通过IP地址定位主机,选择最优传输路径IP(IPv4/IPv6)、ICMP(控制报文协议,如ping)、ARP(IP转MAC)、RARP(MAC转IP)路由器、三层交换机数据包、IP地址(网络逻辑地址)不同局域网间数据跨网段传输
4. 传输层提供端到端通信服务,控制数据传输的可靠性/效率,处理顺序、流量、差错控制TCP(面向连接、可靠传输)、UDP(无连接、高效传输)无(依赖主机操作系统)字节流(TCP)、数据报(UDP)、端口号(进程标识)文件传输(TCP)、视频会议(UDP)
5. 应用层直接为用户应用程序提供服务,定义应用间通信的协议与数据格式HTTP(网页浏览)、HTTPS(安全网页)、FTP(文件传输)、SMTP(邮件发送)、DNS(域名解析)计算机、服务器(运行应用程序)应用数据(如HTML、文件、邮件内容)网页访问、文件上传下载、邮件发送
3. IP 地址深度解析
  • 结构IP = 网络位 + 主机位(通过子网掩码区分),例:192.168.0.121/24 中,24 表示网络位占 24 位。
  • IP地址分类
    类别范围子网掩码应用场景
    A1.0.0.0~126.255.255.255255.0.0.0大规模网络
    B128.0.0.0~191.255.255.255255.255.0.0中大规模网络
    C192.0.0.0~223.255.255.255255.255.255.0中小规模网络
    D224.0.0.0~239.255.255.255-组播/广播
    E240.0.0.0~255.255.255.254-实验用途
  • 特殊地址
    • 私网 IP(如 10.0.0.0/8192.168.0.0/16):局域网内使用,无法直连互联网。
    • 回环地址(127.0.0.0/8):用于本机进程间通信。
4. 端口号

16位整形数据(unsigned short)0 ~65535
功能:标记同一主机的不同网络进程

范围类型说明典型协议/应用
1~1023知名端口系统/通用服务保留HTTP(80)、FTP(20/21)、HTTPS(443)、TFPT(69)
1024~49151注册端口特殊服务使用(需 IANA 分配)MQTT(1883/8883)
49152~65535动态/私有端口应用临时分配客户端随机端口

在这里插入图片描述

三、网络调试与配置工具

工具作用示例命令
ping检测网络连通性ping www.baidu.com
ifconfigLinux 查看/配置 IPifconfig eth0
ipconfigWindows 查看 IPipconfig /all
虚拟机网络配置桥接模式(直连局域网)、NAT(共享主机网络)VMware 中设置“桥接模式”

Linux下:
修改网络配置文件:sudo vim/etc/network/interfaces
重启网络服务:sudo /etc/init.d/networking restart
测试: ping www.baidu.com

四、网络编程实践(UDP 为例)

1. C/S 模型对比
模型客户端特点开发场景资源加载方式
B/S通用(浏览器)主要开发服务端全依赖服务端加载
C/S专用客户端服务端 + 客户端都需开发本地可缓存资源 ,无需所有数据都请求服务器
2. UDP 编程流程(C/S 架构)
  • 服务端socket()bind()recvfrom()sendto()close()
  • 客户端socket()sendto()recvfrom()close()

五、关键函数解析

函数功能核心参数说明
socket()创建套接字domain(AF_INET=IPv4)、type(SOCK_DGRAM=UDP)
bind()绑定 IP+端口需指定 struct sockaddr_in(含 IP、端口)
sendto()发送数据需传入对端地址(dest_addr
recvfrom()接收数据可获取发送端地址(src_addr
socket:创建套接字
int socket(int domain, int type, int protocol);
  • 功能:创建一个网络套接字(通信端点),返回用于后续网络操作的文件描述符。
  • 参数
    • domain:地址族(协议族),指定网络通信的地址类型。常用值:AF_INET(IPv4)、AF_INET6(IPv6)。
    • type:套接字类型,指定通信方式。常用值:SOCK_STREAM(TCP,面向连接、可靠传输)、SOCK_DGRAM(UDP,无连接、不可靠传输)。
    • protocol:具体协议,通常填 0 表示使用 type 对应的默认协议(如 SOCK_STREAM 对应 TCP,SOCK_DGRAM 对应 UDP)。
  • 返回:成功返回非负套接字描述符(sockfd),失败返回 -1(需检查 errno)。
bind:绑定 IP + 端口
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • 功能:将套接字 sockfd 与指定的 IP + 端口 绑定,让系统知道该套接字监听哪个地址。
  • 参数
    • sockfd:套接字(socket() 返回的文件描述符)。
    • addr:要绑定的地址(需强转为 struct sockaddr *,通常用 struct sockaddr_in 填充)。
    • addrlen:地址结构体的大小(sizeof(struct sockaddr_in))。
  • 返回:成功返回 0,失败返回 -1(需检查 errno)。
sendto:发送 UDP 数据到指定地址

(补充说明,与之前知识联动)

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
  • 功能:向指定地址(dest_addr)发送 UDP 数据。
  • 参数
    • dest_addr:接收方的地址(struct sockaddr_in 填充 IP + 端口)。
recvfrom:接收 UDP 数据并获取发送方地址
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
  • 功能:从套接字 sockfd 接收数据,同时获取 发送方的地址信息src_addr)。
  • 参数
    • sockfd:套接字。
    • buf:存储接收数据的缓冲区。
    • len:希望接收的最大字节数。
    • flags:通常填 0(阻塞接收)。
    • src_addr:用于存储 发送方地址(需用 struct sockaddr_in 解析)。
    • addrlen:地址结构体的大小(传入 sizeof(src_addr) 的指针)。
  • 返回:成功返回实际接收的字节数,失败返回 -1
网络地址结构体(struct sockaddr_in

用于描述 IPv4 网络地址,是 UDP/TCP 编程的基础数据结构。

struct sockaddr_in {sa_family_t  sin_family;    // 地址族(固定为 AF_INET 表示 IPv4)in_port_t    sin_port;      // 端口号(网络字节序)struct in_addr sin_addr;    // IP 地址(网络字节序)
};// IP 地址的二进制形式(网络字节序)
struct in_addr {uint32_t s_addr; 
};
参数:
  1. sin_family
    • 必须填 AF_INET(表示 IPv4 地址族),否则通信失败。
  2. sin_port
    • 存储 端口号,但必须用 网络字节序(通过 htons 转换)。
  3. sin_addr
    • 存储 IP 地址(二进制形式,网络字节序),常用 inet_addrinet_pton 转换字符串 IP。
字节序转换(网络大端 vs 主机小端 )

网络通信要求 端口号、IP 地址 必须用 网络字节序(大端),而主机 CPU 可能是 小端,因此需要转换。

1. 核心函数
函数功能适用场景
htons(host_short)主机短整型 → 网络字节序端口号转换(16 位)
ntohs(net_short)网络字节序 → 主机短整型端口号转换(16 位)
htonl(host_long)主机长整型 → 网络字节序IP 地址转换(32 位)
ntohl(net_long)网络字节序 → 主机长整型IP 地址转换(32 位)
2. 示例(端口号转换)
uint16_t host_port = 50000;   // 主机字节序(小端)
uint16_t net_port = htons(host_port); // 转换为网络字节序(大端)
3. 字节序直观对比
  • 主机小端(x86 架构):低字节存低地址,例:0x1234 存储为 0x34 0x12
  • 网络大端:高字节存低地址,例:0x1234 存储为 0x12 0x34
IP 地址字符串 ↔ 二进制转换
  • inet_addr(const char *cp)

    • 功能:将字符串 IP(如 "192.168.0.171")转换为 网络字节序的二进制 IPuint32_t)。
    • 示例:
      struct in_addr ip;
      ip.s_addr = inet_addr("192.168.0.171"); // 转换为网络字节序
      
  • inet_ntoa(struct in_addr in)

    • 功能:将二进制 IP(网络字节序)转换为 字符串 IP(如 "192.168.0.171")。
    • 示例:
      struct in_addr ip = {.s_addr = inet_addr("192.168.0.171")};
      char *ip_str = inet_ntoa(ip); // 转换为字符串 "192.168.0.171"
      

六、练习(UDP 全双工通信)

  • 服务端(server.c

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>int main() {int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 创建 UDP 套接字struct sockaddr_in addr = {.sin_family = AF_INET, .sin_port = htons(50000), .sin_addr.s_addr = INADDR_ANY};bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)); // 绑定端口char buf[1024];struct sockaddr_in client_addr;socklen_t len = sizeof(client_addr);while (1) {// 接收客户端数据 + 获取客户端地址ssize_t cnt = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&client_addr, &len);buf[cnt] = '\0';printf("收到来自 %s:%d 的数据:%s\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), buf);// 回复客户端sendto(sockfd, "已收到", 6, 0, (struct sockaddr*)&client_addr, len);}close(sockfd);return 0;
    }
    
  • 客户端(client.c

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>int main() {int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 创建 UDP 套接字struct sockaddr_in server_addr = {.sin_family = AF_INET, .sin_port = htons(50000), .sin_addr.s_addr = inet_addr("192.168.0.171")};char buf[1024];while (1) {fgets(buf, sizeof(buf), stdin); // 从终端读入数据sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr*)&server_addr, sizeof(server_addr)); // 发数据// 接收服务端回复ssize_t cnt = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);buf[cnt] = '\0';printf("服务端回复:%s\n", buf);}close(sockfd);return 0;
    }
    
http://www.dtcms.com/a/344339.html

相关文章:

  • 三,设计模式-抽象工厂模式
  • Ubuntu/Debian修改网卡名字enP3p49s0为eth0
  • JUC之CompletionService
  • 【基础算法】离散化
  • AI-调查研究-58-机器人 从工厂到家庭,机器人正悄悄改变世界的每个角落
  • RCE的CTF题目环境和做题复现第3集
  • 改善收敛性有什么作用?收敛代表什么
  • chrome driver在Mac上运行时提示安全问题怎么解决
  • 一键部署Jaeger:Docker全攻略
  • Simulink不连续模块库(Hit Crossing/PWM/Rate Limiter/Rate Limiter Dynamic)
  • @SerializedName注解详解
  • 【51单片机数码管字符左移】2022-11-11
  • TapData vs Kafka ETL Pipeline:竞争?共存?——企业实时数据策略的正确打开方式
  • Kafka中zk的作用是什么
  • 【ECharts】2. ECharts 性能优化
  • 【在ubuntu下使用vscode打开c++的make项目及编译调试】
  • [antv-x6] 博客案例
  • 英伟达新架构9B模型引领革命,谷歌/阿里/微美全息AI多维布局锻造底座竞争力
  • ROS2下YOLO+Moveit+PCL机械臂自主避障抓取方案
  • Retrieval-Augmented Generation(RAG)
  • 《CF1245D Shichikuji and Power Grid》
  • 雷达图教程:何时适用,何时无效,以及如何正确使用
  • 小智ai+mcp+n8n的智能组合
  • Matplotlib 可视化大师系列(三):plt.bar() 与 plt.barh() - 清晰对比的柱状图
  • 计算机组成原理(10) - 浮点数的表示
  • 全栈开发:从LAMP到云原生的技术革命
  • docker + nginx + pm2 部署前端项目和后端(nodejs)项目
  • setup 语法糖核心要点
  • 第二十八天:多项式求值问题
  • 决策树进阶学习笔记