Linux 入门十一:Linux 网络编程
一、概述
1. 网络编程基础
网络编程是通过网络应用编程接口(API)编写程序,实现不同主机上进程间的信息交互。它解决的核心问题是:如何让不同主机上的程序进行通信。
2. 网络模型:从 OSI 到 TCP/IP
-
OSI 七层模型(理论模型):
物理层(传输比特流)→ 数据链路层(组帧、差错控制)→ 网络层(路由选择,IP 协议)→ 传输层(端到端通信,TCP/UDP)→ 会话层(建立会话)→ 表示层(数据格式转换)→ 应用层(HTTP、FTP 等具体应用)。
特点:层次清晰,适合理论分析,但实际开发中较少直接使用。 -
TCP/IP 四层模型(实用模型):
网络接口层(对应 OSI 下两层,处理硬件通信)→ 网络层(IP 协议,寻址和路由)→ 传输层(TCP/UDP,端到端数据传输)→ 应用层(HTTP、FTP、SMTP 等,具体业务逻辑)。
特点:简化层次,广泛应用于实际开发。
3. 常用网络协议速查表
| 协议名称 | 英文全称 | 核心功能 | 典型场景 |
|---|---|---|---|
| TCP | 传输控制协议 | 面向连接、可靠传输 | 网页浏览(HTTP)、文件传输(FTP) |
| UDP | 用户数据报协议 | 无连接、不可靠传输 | 视频直播、DNS 查询 |
| IP | 网际协议 | 网络层寻址与路由 | 所有网络通信的基础 |
| ICMP | 互联网控制消息协议 | 网络状态检测(如 ping) | 故障排查(ping、traceroute) |
| FTP | 文件传输协议 | 高效传输文件 | 服务器文件共享 |
| SMTP | 简单邮件传输协议 | 发送电子邮件 | 邮件服务器通信 |
二、网络通信三要素:IP、端口、套接字

1. IP 地址:主机的 “门牌号”
- 定义:32 位(IPv4)或 128 位(IPv6)的二进制数,唯一标识网络中的主机。
- IPv4 示例:
192.168.1.1(点分十进制) - IPv6 示例:
2001:0db8:85a3:0000:0000:8a2e:0370:7334(十六进制)
- IPv4 示例:
- 查看本机 IP:终端输入
ifconfig(Linux)或ipconfig(Windows)。 - 特殊 IP:
127.0.0.1:本地回环地址,用于测试本机网络程序。0.0.0.0:监听所有可用网络接口。255.255.255.255:广播地址,向同一网络内所有主机发送数据。
2. 端口号:程序的 “房间号”
- 定义:16 位无符号整数(0-65535),标识同一主机上的不同进程。
- 分类:
- 保留端口(0-1023):系统专用(如 80 端口用于 HTTP,22 端口用于 SSH)。
- 注册端口(1024-49151):分配给特定服务(如 3306 端口用于 MySQL)。
- 动态端口(49152-65535):程序运行时动态申请,避免冲突。
- 注意:编程时避免使用保留端口,可选择 1024 以上未被占用的端口(如 8888、3333)。
3. 套接字(Socket):通信的 “通道”
-
定义:一种特殊的文件描述符,用于跨网络或本地进程通信。
-
三要素:IP 地址 + 端口号 + 传输层协议(TCP/UDP)。
-
类型:
- 流式套接字(SOCK_STREAM):基于 TCP,可靠、面向连接(如打电话,需先接通)。
- 数据报套接字(SOCK_DGRAM):基于 UDP,无连接、不可靠(如发短信,无需确认对方是否在线)。
- 原始套接字(SOCK_RAW):直接访问底层协议(如 IP/ICMP),用于网络开发或抓包工具。
-
地址结构体:
// IPv4 地址结构体(常用) struct sockaddr_in {sa_family_t sin_family; // 地址族,固定为 AF_INET(IPv4)或 AF_INET6(IPv6)in_port_t sin_port; // 端口号(网络字节序,需用 htons 转换)struct in_addr sin_addr; // IP 地址(网络字节序,可用 inet_addr 转换字符串) };// 通用地址结构体(需强制转换使用) struct sockaddr {sa_family_t sa_family; // 地址族char sa_data[14]; // 具体地址数据(不同协议族格式不同) };
三、TCP 编程:可靠的 “快递服务”
1. TCP 核心特点
- 面向连接:通信前需先建立连接(三次握手),通信后释放连接(四次挥手)。
- 可靠传输:通过确认机制、重传机制保证数据有序且无丢失。
- 流式传输:数据像水流一样连续发送,无边界(需应用层自定义消息边界)。
2. TCP 服务器开发步骤(逐步解析)
步骤 1:创建套接字(socket)
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
- 参数:
domain:协议族,IPv4 用AF_INET,IPv6 用AF_INET6,本地通信用AF_UNIX。type:套接字类型,TCP 用SOCK_STREAM,UDP 用SOCK_DGRAM。protocol:具体协议,通常为 0(自动选择对应类型的默认协议,如 TCP 选 IPPROTO_TCP)。
- 返回值:成功返回套接字描述符(文件描述符),失败返回 -1。
- 示例:
int server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd == -1) {perror("socket failed");exit(EXIT_FAILURE); }
步骤 2:绑定地址(bind)
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- 作用:将套接字与本地 IP 地址和端口号绑定,让客户端知道如何连接。
- 参数:
sockfd:步骤 1 创建的套接字描述符。addr:地址结构体指针(需将sockaddr_in强制转换为sockaddr)。addrlen:地址结构体的长度(sizeof(struct sockaddr_in))。
- 示例:
struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; // IPv4 协议族 server_addr.sin_port = htons(8888); // 端口号(htons 转换为网络字节序) server_addr.sin_addr.s_addr = INADDR_ANY; // 监听所有本地 IP(0.0.0.0)if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {perror("bind failed");exit(EXIT_FAILURE); } - 易错点:端口号必须用
htons转换为网络字节序(大端模式),否则无法正确识别。
步骤 3:监听连接(listen)
#include <sys/socket.h>
int listen(int sockfd, int backlog);
- 作用:将套接字设置为被动监听状态,等待客户端连接。
- 参数:
sockfd:已绑定的套接字描述符。backlog:等待连接的最大队列长度(通常设为 5-10,视并发需求而定)。
- 示例:
if (listen(server_fd, 5) == -1) {perror("listen failed");exit(EXIT_FAILURE); }
步骤 4:接受连接(accept)
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
- 作用:阻塞等待客户端连接,成功后返回新的套接字描述符(用于与该客户端通信)。
- 参数:
sockfd:监听套接字描述符。addr:用于存储客户端地址的结构体指针。addrlen:客户端地址结构体的长度(传入前需初始化,传出时自动填充实际长度)。
- 示例:
struct sockaddr_in client_addr; socklen_t client_addr_len = sizeof(client_addr); int client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len); if (client_fd == -1) {perror("accept failed");exit(EXIT_FAILURE); } printf("Client connected: IP %s, Port %d\n",inet_ntoa(client_addr.sin_addr), // 将网络字节序 IP 转换为字符串ntohs(client_addr.sin_port)); // ntohs 将端口号转换为主机字节序 - 关键点:
accept返回的新套接字client_fd专门用于与当前客户端通信,原server_fd继续监听其他客户端。
步骤 5:数据交互(send/recv)
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
send作用:向连接的套接字发送数据(TCP 保证可靠传输)。flags通常设为 0(默认模式)。- 返回值:成功发送的字节数,失败返回 -1。
recv作用:从连接的套接字接收数据。- 返回值:成功接收的字节数,0 表示对方关闭连接,-1 表示失败。
- 示例:
char buffer[1024] = "Hello, Client!"; // 向客户端发送数据 send(client_fd, buffer, strlen(buffer), 0);// 接收客户端数据 memset(buffer, 0, sizeof(buffer)); ssize_t recv_len = recv(client_fd, buffer, sizeof(buffer), 0); if (recv_len > 0) {printf("Received: %s\n", buffer); }
步骤 6:关闭连接(close)
#include <unistd.h>
int close(int fd);
- 作用:释放套接字资源,触发 TCP 四次挥手释放连接。
- 示例:
close(client_fd); // 关闭与客户端的通信套接字 close(server_fd); // 关闭监听套接字
3. TCP 客户端开发步骤(简洁版)
- 创建套接字(同服务器):
int client_fd = socket(AF_INET, SOCK_STREAM, 0); - 连接服务器(connect):
struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8888); server_addr.sin_addr.s_addr = inet_addr("192.168.1.100"); // 服务器 IPif (connect(client_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {perror("connect failed");exit(EXIT_FAILURE); } - 数据交互(send/recv,同服务器)。
- 关闭连接(close)。
四、UDP 编程:轻量的 “明信片” 传输
1. UDP 核心特点
- 无连接:无需提前建立连接,直接发送数据报(类似发短信,无需等待对方确认)。
- 不可靠:不保证数据到达、不保证顺序、不处理重复。
- 高效:省去连接开销,适合实时性要求高但允许少量丢包的场景(如视频通话、DNS)。
2. UDP 服务器开发步骤(对比 TCP)
步骤 1:创建套接字(socket)
int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 类型为 SOCK_DGRAM
步骤 2:绑定地址(bind,同 TCP)
需绑定端口号(可选绑定 IP,通常用 INADDR_ANY 监听所有接口)。
步骤 3:数据交互(sendto/recvfrom)
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
sendto作用:向指定地址发送数据报(需包含目标 IP 和端口)。recvfrom作用:接收数据报,同时获取发送方的地址(用于回复)。- 示例:
struct sockaddr_in client_addr; socklen_t client_addr_len = sizeof(client_addr); char buffer[1024];// 接收客户端数据(含客户端地址) ssize_t recv_len = recvfrom(sockfd, buffer, sizeof(buffer), 0,(struct sockaddr *)&client_addr, &client_addr_len); if (recv_len > 0) {printf("Received from %s:%d: %s\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port), buffer); }// 回复客户端(用接收到的地址发送) sendto(sockfd, "Hello from server", 18, 0,(struct sockaddr *)&client_addr, client_addr_len);
步骤 4:关闭套接字(close)
同 TCP,直接关闭即可(无连接释放过程)。
3. UDP 客户端开发步骤
- 创建套接字(socket)。
- 可选绑定端口(若不绑定,系统自动分配临时端口)。
- 发送 / 接收数据(sendto/recvfrom,需指定服务器地址)。
- 关闭套接字(close)。
五、高级编程:处理多连接与性能优化
1. IO 多路复用:select 函数(解决单线程多连接阻塞问题)
核心作用
允许单线程同时监听多个套接字,当任意一个套接字就绪(可读 / 可写 / 异常)时,触发响应。
适用场景:客户端数量多但活动连接少的场景(如聊天服务器)。
函数原型
#include <sys/select.h>
int select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,const struct timeval *timeout);
- 参数:
maxfd:监听的最大文件描述符 + 1(确保包含所有监听的 fd)。readfds:可读事件集合(监听哪些 fd 有数据可读)。writefds:可写事件集合(监听哪些 fd 可以写数据)。exceptfds:异常事件集合(通常用不到,设为 NULL)。timeout:超时时间(NULL表示永久阻塞,{0, 0}表示立即返回)。
- 返回值:就绪的文件描述符数量,0 表示超时,-1 表示错误。
使用步骤(以 UDP 服务器监听为例)
- 初始化 fd_set:
fd_set read_fds; FD_ZERO(&read_fds); // 清空集合 FD_SET(sockfd, &read_fds); // 将套接字添加到可读集合 - 计算 maxfd:
int maxfd = sockfd; // 若有多个 fd,取最大值 - 调用 select:
struct timeval tv = {2, 0}; // 超时时间 2 秒 int ready_fds = select(maxfd + 1, &read_fds, NULL, NULL, &tv); if (ready_fds == -1) {perror("select error");exit(EXIT_FAILURE); } else if (ready_fds == 0) {printf("Timeout, no data received\n");continue; } - 检查就绪的 fd:
if (FD_ISSET(sockfd, &read_fds)) {// 处理数据接收recvfrom(sockfd, buffer, sizeof(buffer), 0, &client_addr, &client_addr_len); }
2. 非阻塞 IO:fcntl 函数(避免阻塞等待)
核心作用
将套接字设置为非阻塞模式,使 recv/accept 等操作立即返回,配合轮询或事件驱动处理多任务。
函数原型
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */);
- 设置非阻塞模式:
int flags = fcntl(sockfd, F_GETFL); // 获取当前文件状态标志 fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); // 添加非阻塞标志 - 应用场景:
- 客户端同时发送和接收数据(如聊天程序边输入边接收消息)。
- 服务器需要处理大量并发连接,避免单个连接阻塞整个程序。
六、实战:简单 TCP 服务器与客户端(完整代码)
1. TCP 服务器代码(server.c)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>#define PORT 8888
#define MAX_CLIENTS 5int main() {// 1. 创建监听套接字int server_fd = socket(AF_INET, SOCK_STREAM, 0);if (server_fd < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}// 2. 绑定地址struct sockaddr_in server_addr;server_addr.sin_family = AF_INET;server_addr.sin_port = htons(PORT);server_addr.sin_addr.s_addr = INADDR_ANY;if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {perror("bind failed");exit(EXIT_FAILURE);}// 3. 开始监听if (listen(server_fd, MAX_CLIENTS) < 0) {perror("listen failed");exit(EXIT_FAILURE);}printf("Server listening on port %d...\n", PORT);while (1) {// 4. 接受客户端连接struct sockaddr_in client_addr;socklen_t client_addr_len = sizeof(client_addr);int client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len);if (client_fd < 0) {perror("accept failed");continue;}// 5. 与客户端通信char buffer[1024] = {0};ssize_t recv_len = recv(client_fd, buffer, sizeof(buffer), 0);if (recv_len > 0) {printf("Received: %s\n", buffer);send(client_fd, "Message received", 16, 0);}// 6. 关闭客户端连接close(client_fd);}close(server_fd);return 0;
}
2. TCP 客户端代码(client.c)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>#define PORT 8888
#define SERVER_IP "127.0.0.1"int main() {// 1. 创建客户端套接字int client_fd = socket(AF_INET, SOCK_STREAM, 0);if (client_fd < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}// 2. 连接服务器struct sockaddr_in server_addr;server_addr.sin_family = AF_INET;server_addr.sin_port = htons(PORT);if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {perror("invalid server IP address");exit(EXIT_FAILURE);}if (connect(client_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {perror("connection failed");exit(EXIT_FAILURE);}// 3. 发送数据给服务器char *message = "Hello, Server!";send(client_fd, message, strlen(message), 0);// 4. 接收服务器回复char buffer[1024] = {0};ssize_t recv_len = recv(client_fd, buffer, sizeof(buffer), 0);if (recv_len > 0) {printf("Received from server: %s\n", buffer);}// 5. 关闭连接close(client_fd);return 0;
}
3. 编译与运行
- 编译服务器:
gcc server.c -o server ./server # 启动服务器 - 编译客户端:
gcc client.c -o client ./client # 启动客户端(输出服务器回复)
七、常见易错点与最佳实践
1. 字节序转换:必须使用 htons/htonl/ntohs/ntohl
- 原因:不同主机可能采用小端(x86)或大端(ARM)字节序,网络协议规定使用大端(网络字节序)。
- 错误示例:直接赋值端口号
server_addr.sin_port = 8888;(未用 htons 转换,导致端口错误)。 - 正确做法:
server_addr.sin_port = htons(8888);。
2. 端口冲突:绑定前检查端口是否被占用
- 检查命令:
netstat -tunlp | grep 端口号(查看端口占用情况)。 - 解决方案:更换端口号,或确保上次运行的程序已正确关闭(避免 TIME_WAIT 状态残留)。
3. IP 地址转换:inet_addr 与 inet_pton 的区别
inet_addr:将点分十进制字符串转换为网络字节序(IPv4 专用,过时函数,建议用inet_pton)。inet_pton:支持 IPv4 和 IPv6,返回值更安全(成功返回 1,无效地址返回 0,错误返回 -1)。
4. 缓冲区溢出:固定缓冲区大小需谨慎
- 风险:接收数据时未限制长度可能导致缓冲区溢出(如
recv(client_fd, buffer, sizeof(buffer), 0);是安全的,而recv(client_fd, buffer, 1024, 0);若缓冲区不足 1024 字节则危险)。 - 最佳实践:缓冲区大小固定为已知值,或使用动态内存分配(如 malloc)。
八、拓展学习:从入门到进阶
1. 必学工具
- Wireshark:网络抓包工具,分析 TCP 三次握手、UDP 数据报格式。
- netstat / ss:查看网络连接、端口状态(如
netstat -an显示所有连接)。 - telnet / nc:测试端口连通性(如
telnet 127.0.0.1 8888检查服务器是否运行)。
2. 进阶知识点
- HTTP 协议解析:基于 TCP 实现简单 Web 服务器(处理 GET/POST 请求)。
- 多线程 / 多进程服务器:使用 pthread 或 fork 处理并发连接(解决 select 处理海量连接的性能瓶颈)。
- IPv6 支持:修改地址结构体为
sockaddr_in6,协议族用AF_INET6,实现跨 IPv4/IPv6 的兼容性。
3. 学习资源
- 《UNIX 网络编程》:经典教材,深入理解套接字编程与协议细节。
- Linux 官方文档:
man 2 socket查看系统调用手册,man 7 ip了解 IP 协议细节。
总结
Linux 网络编程是实现跨主机通信的核心技术,从基础的 TCP/UDP 套接字编程,到处理并发的 select/fcntl 高级技巧,需要逐步实践和调试。初学者应先掌握 TCP 服务器 / 客户端的基本流程,理解字节序、地址绑定等核心概念,再通过实战项目(如简易聊天室、文件传输工具)巩固知识。记住,网络编程的关键在于理解协议原理和处理边界条件(如连接中断、数据丢失),多写代码、多抓包分析,才能真正掌握这门技术。
相关文章:
Linux 入门十一:Linux 网络编程
一、概述 1. 网络编程基础 网络编程是通过网络应用编程接口(API)编写程序,实现不同主机上进程间的信息交互。它解决的核心问题是:如何让不同主机上的程序进行通信。 2. 网络模型:从 OSI 到 TCP/IP OSI 七层模型&…...
沐渥氮气柜控制板温湿度氧含量氮气流量四显智控系统
氮气柜控制板通常用于实时监控和调节柜内环境参数,确保存储物品如电子元件、精密仪器、化学品等,处于低氧、干燥的稳定状态。以下是沐渥氮气柜控制板核心参数的详细介绍及控制逻辑: 一、控制板核心参数显示模块 1)温度显示&am…...
vue3 主题模式 结合 element-plus的主题
vue3 主题模式 结合 element-plus的主题 npm i element-plus --save-dev在 Vue 3 中,实现主题模式主要有以下几种方式 1.使用 CSS 变量(自定义属性) CSS 变量是一种在 CSS 中定义可重用值的方式。在主题模式中,可以将颜色、字体…...
Redis 有序集合(Sorted Set)
Redis 有序集合(Sorted Set) 以下从基础命令、内部编码和使用场景三个维度对 Redis 有序集合进行详细解析: 一、基础命令 命令时间复杂度命令含义zadd key score member [score member …] O ( k l o g ( n ) ) O(klog(n)) O(klog(n))&…...
[c语言日寄]免费文档生成器——Doxygen在c语言程序中的使用
【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是…...
QtCreator的设计器、预览功能能看到程序图标,编译运行后图标消失
重新更换虚拟机(Vmware Kylin),重新编译和配置了很多第三方库后,将代码跑到新的这个虚拟机环境中,但是出现程序图标不可见,占位也消失,后来继续检查ui文件,ui文件图标也异常&#x…...
QT文件和文件夹拷贝操作
1.拷贝文件夹 //(源文件目录路劲,目的文件目录,文件存在是否覆盖) bool copyDirectory(const QString& srcPath, const QString& dstPath, bool coverFileIfExist) { QDir srcDir(srcPath); QDir dstDir(dstPath); if (!dstDir.exi…...
面试常用基础算法
目录 快速排序归并排序堆排序 n n n皇后问题最大和子数组爬楼梯中心扩展法求最长回文子序列分割回文串动态规划求最长回文子序列最长回文子串单调栈双指针算法修改 分割回文串滑动窗口栈 快速排序 #include <iostream> #include <algorithm>using namespace std;…...
Python-24:小R的随机播放顺序
问题描述 小R有一个特殊的随机播放规则。他首先播放歌单中的第一首歌,播放后将其从歌单中移除。如果歌单中还有歌曲,则会将当前第一首歌移到最后一首。这个过程会一直重复,直到歌单中没有任何歌曲。 例如,给定歌单 [5, 3, 2, 1,…...
悬空引用和之道、之禅-《分析模式》漫谈57
DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 “Analysis Patterns”的第5章“对象引用”原文: Unless you can catch all such references, there is the risk of a dangling reference, which often has painful con…...
Python accumulate 函数详解
https://docs.python.org/zh-cn/3/library/itertools.html#itertools.accumulate 在 Python 中,accumulate 是一个生成器(generator), 是来自 itertools 模块的一个函数。 它的作用是返回一个迭代器,该迭代器生成输入数据的累积结…...
Cursor可视化大屏搭建__0420
主题:用Cursor怎么进行数据洞察,做AI预测化内容。 Python基础语法与AI python生态强大,代码简洁,相对其他语言Python更好上手,浙江高考将Python列为可选科目 科学计算:Sklearn,Numpy,Pandas 人工智能:Tensorflow,Pytorch 网络爬虫:Scrapy…...
【初阶数据结构】树——二叉树(上)
文章目录 目录 前言 一、树 1.树的概念与结构 2.树相关术语 3.树的表示 二、二叉树 1.概念与结构 2.特殊的二叉树 3.二叉树存储结构 总结 前言 本篇带大家学习一种非线性数据结构——树,简单认识树和二叉数以及了解二叉树的存储结构。 一、树 1.树的概念与结构 树…...
ECharts散点图-散点图14,附视频讲解与代码下载
引言: ECharts散点图是一种常见的数据可视化图表类型,它通过在二维坐标系或其它坐标系中绘制散乱的点来展示数据之间的关系。本文将详细介绍如何使用ECharts库实现一个散点图,包括图表效果预览、视频讲解及代码下载,让你轻松掌握…...
C++中的算术转换、其他隐式类型转换和显示转换详解
C中的类型转换(Type Conversion)是指将一个数据类型的值转换为另一个数据类型的过程,主要包括: 一、算术类型转换(Arithmetic Conversions) 算术类型转换通常发生在算术运算或比较中,称为**“标…...
GAIA-2:用于自动驾驶的可控多视图生成世界模型
25年3月来自英国创业公司 Wayze 的论文“GAIA-2: A Controllable Multi-View Generative World Model for Autonomous Driving”。(注:23年9月其发布GAIA-1) 生成模型为模拟复杂环境提供一种可扩展且灵活的范例,但目前的方法不足…...
(一)CMake / MsBuild Ninja Make/ MSVC g++ clang++ 等c++编译概念解释
c 几个编译概念 一 概念二 层级关系总结2.1层级表格2.2 关键点说明2.3 示例流程(以 Ninja 为例)2.4 示例流程(Windows 平台) 三 总结 一 概念 CMake 通过 CMakeLists.txt 生成不同平台的构建文件(如 .sln、build.n…...
创建 Node.js Playwright 项目:从零开始搭建自动化测试环境
一、环境准备 在开始创建 Playwright 项目之前,确保你的电脑上已经安装了以下工具: Node.js:Playwright 依赖于 Node.js 环境,确保你已经安装了最新版本的 Node.js。可以通过以下命令检查是否安装成功: node -v npm -…...
浅谈AI致幻
文章目录 当前形势下存在的AI幻觉(AI致幻)什么是AI幻觉AI幻觉的类型为什么AI会产生幻觉AI幻觉的危害与影响当前应对AI幻觉的技术与方法行业与学术界的最新进展未来挑战与展望结论 当前形势下存在的AI幻觉(AI致幻) 什么是AI幻觉 …...
postman乘法计算,变量赋值
postman脚本怎么计算乘法 在Postman中,你可以通过多种方式计算乘法,这取决于你的具体需求。例如,如果你想在发送请求前计算乘法结果,或者在测试标签中计算响应数据的乘法,下面是一些常见的方法。 1. 使用JavaScript代…...
自定义错误码的必要性
为什么要使用错误码,直接返回一个错误信息不好么? 下面介绍一下,在程序开发中使用错误码的必要性~ 便于排查问题 想象你开了一家奶茶店,顾客下单后可能出现各种问题: 没珍珠了(错误码:50…...
车载软件架构 --- 二级boot设计说明需求规范
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…...
管理杂谈——采石矶大捷的传奇与启示
南宋抗金史上,岳飞与岳家军的铁血传奇家喻户晓,但另一位力挽狂澜的“文官战神”却常被忽视——他从未掌兵,却在南宋存亡之际整合溃军,以少胜多,缔造采石矶大捷。此人正是虞允文。一介书生何以扭转乾坤?他的…...
Java高效合并Excel报表实战:GcExcel让数据处理更简单
前言:为什么需要自动化合并Excel? 在日常办公场景中,Excel报表合并是数据分析的基础操作。根据2023年企业办公效率报告显示: 财务人员平均每周花费6.2小时在Excel合并操作上人工合并的错误率高达15%90%的中大型企业已采用自动化…...
第十四届蓝桥杯 2023 C/C++组 平方差
目录 题目: 题目描述: 题目链接: 思路: 核心思路: 第一种思路: 第二种思路: 坑点: 代码: 数学找规律 O(n) 50分代码详解: O(1)满分代码详解&#x…...
前端路由缓存实现
vue3缓存实现完整版,查看这篇设计和实现方式吧,更完整...
I/O复用函数的使用——select
I/O复用函数的使用——select 目录 一、概念 二、select接口 2.1 基础概念 2.2 使用 select 函数的标准输入读取代码 2.3 基于 select 模型的多客户端 TCP 服务器实现 一、概念 i/o复用使得程序能同时监听多个文件描述符,可以提高程序性能。 之前为了让服务器能…...
ubuntu20.04安装安装x11vnc服务基于gdm3或lightdm这两种主流的显示管理器。
前言:在服务端安装vnc服务,可以方便的远程操作服务器,而不用非要插上显示器才行。所以在服务器上安装vnc是很重要的。在ubuntu20中,默认的显示管理器已经变为gdm3,它可以带来与 GNOME 无缝衔接的体验,强调功…...
图像预处理-图像轮廓特征查找
其实就是外接轮廓,有了轮廓点就可以找到最上、最下、最左、最右的四个坐标(因为有xmin,xmax,ymin,ymax)。就可以绘制出矩形。 一.外接矩形 cv.boundingRect(轮廓点) - 返回x,y,w,h,传入一个轮廓的轮廓点,若有多个轮廓需…...
全同态加密医疗数据分析集python实现
目录 摘要一、前言二、全同态加密与医疗数据分析概述2.1 全同态加密(FHE)简介2.2 医疗数据分析需求三、数据生成与预处理四、系统架构与流程4.1 系统架构图五、核心数学公式六、异步任务调度与(可选)GPU 加速七、PyQt6 GUI 设计八、完整代码实现九、自查测试与总结十、展望…...
