Linux C/C++ Socket 编程
本文目录
- Linux C语言 socket 编程 client 端
- 头文件 unistd.h & arpa/inet.h
- 1. **`unistd.h`**
- 2. **`arpa/inet.h`**
- socket() 创建套接字
- sockaddr_in 结构体
- inet_pton()
- connect()
- send()
- recv()
- send() 和 recv() 中的 flags 参数
- **默认行为(`flags = 0`)的特点:**
- 其他 `flags` 标志:
- close()
- 使用 C++ 面向对象编程思想封装
- Linux C语言 socket 编程 server 端
- setsockopt()
- bind()
- listen()
- accept()
- read()
- server 端 C++
- 运行
- Linux socket 编程在线英文文档
进行网络套接字编程之前,需要有计算机网络相关方面的知识。
Linux C语言 socket 编程 client 端
// client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>#define SERVER_IP "127.0.0.1" // 服务器地址
#define SERVER_PORT 12000 // 服务器端口int main() {// 创建套接字int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd == -1) {perror("Socket creation failed");exit(EXIT_FAILURE);}// 设置服务器信息struct sockaddr_in server_addr;memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(SERVER_PORT);// 将服务器的 IP 地址转换为二进制形式if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {perror("Invalid address or Address not supported");close(sockfd);exit(EXIT_FAILURE);}// 连接到服务器if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {perror("Connection failed");close(sockfd);exit(EXIT_FAILURE);}// 发送数据char *message = "Hello, server!";if (send(sockfd, message, strlen(message), 0) == -1) {perror("Send failed");close(sockfd);exit(EXIT_FAILURE);}printf("Message sent to server: %s\n", message);// 接收数据char buffer[1024];int bytes_received = recv(sockfd, buffer, sizeof(buffer) - 1, 0);if (bytes_received == -1) {perror("Recv failed");close(sockfd);exit(EXIT_FAILURE);}buffer[bytes_received] = '\0'; // 添加字符串终止符printf("Received from server: %s\n", buffer);// 关闭套接字close(sockfd);return 0;
}
编译:gcc -o client client.c
Terminal 下运行:./client
头文件 unistd.h & arpa/inet.h
这两个头文件 unistd.h 和 arpa/inet.h 都是 POSIX 标准 下的系统头文件,广泛用于 Unix/Linux 系统上的编程,尤其是网络编程和低级系统调用。
1. unistd.h
unistd.h 是一个与 Unix 系统调用相关的头文件,提供了大量与操作系统交互的功能,例如文件操作、进程管理、内存管理、IO 操作等。
常用功能:
-
文件操作:
read(): 读取文件描述符中的数据。write(): 向文件描述符写入数据。close(): 关闭文件描述符。
-
进程控制:
fork(): 创建一个新进程(分叉)。exec(): 替换当前进程的执行映像。getpid(): 获取当前进程的 PID。getppid(): 获取父进程的 PID。
-
文件描述符操作:
dup(),dup2(): 复制文件描述符。pipe(): 创建管道。
-
时间管理:
sleep(): 使当前进程睡眠指定的秒数。usleep(): 使当前进程睡眠指定的微秒数。
-
系统信息:
getcwd(): 获取当前工作目录。
这些函数大多数涉及操作系统级别的基本功能,因此它们的效率高,广泛应用于各种系统编程中。
2. arpa/inet.h
arpa/inet.h 是与 Internet 地址处理 和 网络通信 相关的头文件,提供了对 IP 地址和端口号进行转换、网络字节序与主机字节序之间转换等功能。这些函数对于进行 网络编程,尤其是 TCP/IP 网络通信 非常重要。
常用功能:
-
IP 地址转换:
inet_pton(): 将 IP 地址从点分十进制字符串转换为网络字节序的二进制格式(用于struct sockaddr_in)。inet_ntop(): 将网络字节序的 IP 地址转换为点分十进制字符串。
-
主机字节序与网络字节序转换:
htons(): 将 16 位短整数从主机字节序转换为网络字节序(例如端口号)。htonl(): 将 32 位长整数从主机字节序转换为网络字节序(例如 IP 地址)。ntohs(): 将 16 位短整数从网络字节序转换为主机字节序。ntohl(): 将 32 位长整数从网络字节序转换为主机字节序。
这些函数通常用于 TCP/IP 套接字编程中,帮助程序处理地址、端口号的转换和网络字节序问题。
socket() 创建套接字
// 创建套接字
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {perror("Socket creation failed");exit(EXIT_FAILURE);
}
在 linux 系统上,可以使用 man 命令(Linux Manual Pages (man pages))来查看大部分 Linux 系统调用的文档,man 2 socket:查看 socket() 函数的详细文档:
$ man 2 socket
-----------------------------
socket(2) System Calls Manual socket(2)NAMEsocket - create an endpoint for communicationLIBRARYStandard C library (libc, -lc)SYNOPSIS#include <sys/socket.h>int socket(int domain, int type, int protocol);DESCRIPTIONsocket() creates an endpoint for communication and returns a file descriptor that refers to that endpoint. The file descriptor returned by a suc‐cessful call will be the lowest-numbered file descriptor not currently open for the process.The domain argument specifies a communication domain; this selects the protocol family which will be used for communication. These families aredefined in <sys/socket.h>. The formats currently understood by the Linux kernel include:Name Purpose Man pageAF_UNIX Local communication unix(7)AF_LOCAL Synonym for AF_UNIXAF_INET IPv4 Internet protocols ip(7)AF_AX25 Amateur radio AX.25 protocol ax25(4)AF_IPX IPX - Novell protocols
... ...
... ...
... ...
socket() 是一个系统调用,用于创建一个新的套接字。套接字是进行网络通信的基础,通过它可以实现数据的发送和接收。socket() 函数会返回一个 套接字描述符,它是一个整数值,后续的网络操作(如连接、发送、接收等)都需要通过这个描述符进行。
socket() 函数第一个参数常用的有 AF_INET (IPv4 地址族)和 AF_INET6 (IPv6 地址族)。第二个参数常用的有 SOCK_STREAM (TCP)和 SOCK_DGRAM (UDP)。第三个参数-通常指定套接字使用的协议。对于 SOCK_STREAM 类型,协议值通常设置为 0,表示使用默认协议。在 IPv4 上,默认协议就是 TCP,在 SOCK_DGRAM 类型下,默认协议是 UDP。如果使用 AF_INET6,则可以使用 IPPROTO_TCP 或 IPPROTO_UDP 来指定具体协议。
返回值:如果成功,则返回新套接字的文件描述符。如果失败,则返回 -1,并 适当设置 errno 。
sockaddr_in 结构体
struct sockaddr_in 是一个结构体,用来表示 IPv4 地址和端口信息。它定义在 <netinet/in.h> 头文件中,通常用于套接字编程中存储 IP 地址和端口信息。
// definition
struct sockaddr_in
{short sin_family; /* must be AF_INET */u_short sin_port;struct in_addr sin_addr;char sin_zero[8]; /* Not used, must be zero */
};
// 设置服务器信息struct sockaddr_in server_addr;memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(SERVER_PORT);
memset() 的作用是将指定的内存区域填充为特定的值。这里将 server_addr 结构体的所有字节设置为 0,这样可以确保结构体中的所有字段都初始化为 0,防止未初始化的字段造成意外行为。
-
htons()是一个用于 字节序转换 的函数。它的作用是将 主机字节序(即本机的字节序)转换为 网络字节序(即大端字节序)。- 网络字节序:大端字节序(big-endian),即高位字节存储在低地址。
- 主机字节序:通常是小端字节序(little-endian),但这取决于机器架构。
-
端口号是 16 位的整数,通常我们使用
htons()来确保在网络传输时,端口号以网络字节序的格式进行传输。
inet_pton()
inet_pton - convert IPv4 and IPv6 addresses from text to binary form(IP 地址转换成二进制形式)。
definition:
#include <arpa/inet.h>int inet_pton(int af, const char *src, void *dst);
返回值:成功返回 1 。src IP 地址格式错误返回 0 。af 不合法 返回 -1 。
connect()
#include <sys/socket.h>
int connect(int socket, const struct sockaddr *address, socklen_t address_len);
返回值:成功返回0,其他返回 -1 。
send()
#include <sys/socket.h>
ssize_t send(int socket, const void *buffer, size_t length, int flags);
返回值:发送成功,返回发送数据的字节数;失败,返回 -1 。
recv()
#include <sys/socket.h>
ssize_t recv(int socket, void *buffer, size_t length, int flags);
返回值:接收数据成功返回接收数据的字节数;如果没有数据接收且对方已有序关闭连接返回 0;其他错误情况返回 -1 。
send() 和 recv() 中的 flags 参数
send() 和 recv() 的 flags 参数通常设置为 0,表示使用默认的行为模式。
默认行为(flags = 0)的特点:
- 阻塞模式:
send()和recv()默认都处于阻塞模式,意味着:send():如果数据无法立刻发送(比如网络缓冲区已满),它会阻塞,直到有足够的空间可以发送数据。recv():如果没有数据可读,它会阻塞,直到接收到至少一个字节的数据,或者对方关闭了连接。
- 按字节顺序发送/接收:
send()会按顺序发送数据,recv()会按顺序接收数据,返回已接收到的字节数。如果请求的数据量比接收到的少,recv()会返回已接收到的字节数,剩余的数据需要在后续调用中接收。 - 正常的数据传输:不进行任何特殊处理,如不启用带外数据、不使用非阻塞模式等。
其他 flags 标志:
-
MSG_OOB:- 发送 带外数据(Out-of-Band Data)。通常用于传输紧急数据,但对于大多数应用程序来说,带外数据并不常用。
- 在 TCP 中,带外数据和普通数据并没有严格的区分,标记为带外数据的行为在很多情况下不起作用。
-
MSG_PEEK:- 使
recv()函数或recvfrom()函数可以预读取数据,但数据并不会从缓冲区中被移除。即使数据被读取,下一次调用recv()或recvfrom()仍然会返回相同的数据。 - 这种标志在
recv()上比较常用,但在send()上没有直接用途。
- 使
-
MSG_DONTROUTE:- 发送数据时, 不经过路由表。这个标志告诉内核,不要尝试寻找默认路由,而是直接将数据发送到目标地址。通常用于开发中的调试或非常规的发送需求。
-
MSG_NOSIGNAL:- 当使用该标志时,
send()不会在发送过程中因信号的产生而导致SIGPIPE信号(即破损的管道错误)。通常与管道或套接字连接相关,如果尝试向已关闭的连接发送数据,默认会收到SIGPIPE信号,而通过MSG_NOSIGNAL可以避免这种情况。
- 当使用该标志时,
-
MSG_WAITALL:- 用于
recv()和recvfrom(),告知内核等待直到接收到指定长度的数据。它确保不会返回少于length字节的数据,除非连接关闭。 - 这对于一些需要完整接收数据的场景非常有用,尤其是在接收固定大小的数据时。
- 用于
close()
释放之前创建的套接字的资源。
使用 C++ 面向对象编程思想封装
// client.cpp
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>class TcpClient {
private:int sockfd;struct sockaddr_in server_addr;public:// 构造函数TcpClient(const std::string& server_ip, int server_port) {// 创建套接字sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd == -1) {perror("Socket creation failed");exit(EXIT_FAILURE);}// 设置服务器地址结构memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(server_port);if (inet_pton(AF_INET, server_ip.c_str(), &server_addr.sin_addr) <= 0) {perror("Invalid address or Address not supported");close(sockfd);exit(EXIT_FAILURE);}}// 连接服务器void connectToServer() {if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {perror("Connection failed");close(sockfd);exit(EXIT_FAILURE);}std::cout << "Connected to server\n";}// 发送数据void sendData(const std::string& message) {if (send(sockfd, message.c_str(), message.length(), 0) == -1) {perror("Send failed");close(sockfd);exit(EXIT_FAILURE);}std::cout << "Message sent: " << message << std::endl;}// 接收数据void receiveData() {char buffer[1024];int bytes_received = recv(sockfd, buffer, sizeof(buffer) - 1, 0);if (bytes_received == -1) {perror("Recv failed");close(sockfd);exit(EXIT_FAILURE);}buffer[bytes_received] = '\0'; // Add null terminatorstd::cout << "Received from server: " << buffer << std::endl;}// 关闭套接字void closeConnection() {close(sockfd);}// 析构函数~TcpClient() {closeConnection();}
};int main() {TcpClient client("127.0.0.1", 12000);client.connectToServer();client.sendData("Hello, server!");client.receiveData();return 0;
}
编译:g++ -o client client.cpp
Linux C语言 socket 编程 server 端
// server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> // 提供 close、read 和 write (这里通过 send 间接使用,因为 send 是 write 的一个更高级别的封装)
#include <arpa/inet.h> // 提供了用于网络地址转换的函数声明,如将点分十进制格式的 IP 地址转换为网络字节序,以及将端口号从主机字节序转换为网络字节序。#define PORT 12000 // socket 绑定的端口好
#define BUFFER_SIZE 1024 // 缓存大小int main() {int server_fd, new_socket;struct sockaddr_in address; // 结构体,用于存储 IPv4 地址和端口号的信息。int opt = 1;int addrlen = sizeof(address);char buffer[BUFFER_SIZE] = {0};const char *hello = "Hello from server";// 创建socketif ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {/*AF_INET:指定地址族为 IPv4。SOCK_STREAM:指定套接字类型为 TCP(面向连接的字节流)。0:指定协议为 0,通常对于 SOCK_STREAM 和 AF_INET,这个参数为 0,意味着使用 TCP。*/perror("socket failed");exit(EXIT_FAILURE);}// 绑定socket到端口if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {perror("setsockopt");exit(EXIT_FAILURE);}address.sin_family = AF_INET; // IPv4address.sin_addr.s_addr = INADDR_ANY; // 任何地址address.sin_port = htons(PORT); // 端口if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {perror("bind failed");exit(EXIT_FAILURE);}// 监听连接if (listen(server_fd, 3) < 0) {perror("listen");exit(EXIT_FAILURE);}// 接受连接while (1) {printf("等待连接...\n");if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {perror("accept");exit(EXIT_FAILURE);}// 接收数据read(new_socket, buffer, BUFFER_SIZE);printf("收到消息: %s\n", buffer);// 发送数据send(new_socket, hello, strlen(hello), 0);printf("欢迎消息已发送\n");// 关闭当前连接close(new_socket);}// 关闭服务器socketclose(server_fd);return 0;
}
编译:gcc -o server server.c
setsockopt()
#include <sys/socket.h>
int setsockopt(int socket, int level, int option_name,const void *option_value, socklen_t option_len);
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {perror("setsockopt");exit(EXIT_FAILURE);}
setsockopt() 函数,用于设置套接字的选项。是在创建一个服务器套接字时,配置套接字的一些行为或属性。SO_REUSEADDR 选项的设置允许在套接字关闭后,立即重用相同的地址(IP 和端口),而不必等到操作系统回收该端口。
level:指定选项所在的协议层,通常是 SOL_SOCKET,表示设置的是套接字级别的选项。
optval:指向一个存储选项值的内存区域。这个值会根据不同的选项而变化,通常是一个整数或布尔值。
optlen:optval 指向的内存区域的大小(字节数)。
int opt = 1; opt 是 SO_REUSEADDR 选项的值通常是 1(启用)或 0(禁用)。sizeof(opt) 用来确定 opt 变量的大小。
setsockopt() 返回值:设置成功返回 0,否则返回 -1 。
address.sin_addr.s_addr = INADDR_ANY; INADDR_ANY 是一个特殊的常量,值是 0.0.0.0,它代表任何可用的网络接口地址(所有的 IPv4 地址),通常用于绑定套接字到所有本地可用的网络接口,可以使得服务器程序更灵活地接受来自不同网络接口的请求。
bind()
#include <sys/socket.h>
int bind(int socket, const struct sockaddr *address,socklen_t address_len);
返回值:绑定成功成功返回 0,否则返回 -1 。
listen()
#include <sys/socket.h>
int listen(int socket, int backlog);
返回值:监听成功返回 0,否则返回 -1 。
accept()
#include <sys/socket.h>
int accept(int socket, struct sockaddr *restrict address,socklen_t *restrict address_len);
返回值:接受失败返回 -1,成功则返回接受套接字的非负文件描述。
read()
从套接字接收缓存中读取收到的数据。
#include <unistd.h>
ssize_t read(int fildes, void *buf, size_t nbyte);
成功完成后,将返回一个非负整数,表示实际读取的字节数。否则,函数将返回 -1 并设置 errno 以指示错误。
server 端 C++
// server.cpp
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 12000 // 端口
#define BUFFER_SIZE 1024class Server {
public:Server() {server_fd = socket(AF_INET, SOCK_STREAM, 0);if (server_fd < 0) {std::cerr << "Socket creation failed" << std::endl;exit(EXIT_FAILURE);}sockaddr_in address;int addrlen = sizeof(address);address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons(PORT);if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {std::cerr << "Bind failed" << std::endl;close(server_fd);exit(EXIT_FAILURE);}if (listen(server_fd, 3) < 0) {std::cerr << "Listen failed" << std::endl;close(server_fd);exit(EXIT_FAILURE);}std::cout << "Server is listening on port " << PORT << std::endl;}~Server() {close(server_fd);}void acceptConnection() {sockaddr_in address;int addrlen = sizeof(address);int new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);if (new_socket < 0) {std::cerr << "Accept failed" << std::endl;return;}char buffer[BUFFER_SIZE];int valread = read(new_socket, buffer, BUFFER_SIZE);std::cout << "Message from client: " << buffer << std::endl;const char *response = "Hello from server";send(new_socket, response, strlen(response), 0);std::cout << "Response sent to client" << std::endl;close(new_socket);}private:int server_fd;
};int main() {Server server;while (true) {server.acceptConnection();}return 0;
}
编译:g++ -o server server.cpp
运行

Linux socket 编程在线英文文档
点击跳转
相关文章:
Linux C/C++ Socket 编程
本文目录 Linux C语言 socket 编程 client 端头文件 unistd.h & arpa/inet.h1. **unistd.h**2. **arpa/inet.h** socket() 创建套接字sockaddr_in 结构体inet_pton()connect()send()recv()send() 和 recv() 中的 flags 参数**默认行为(flags 0)的特…...
Flutter错误: uses-sdk:minSdkVersion 16 cannot be smaller than version 21 declared
前言 今天要做蓝牙通信的功能,我使用了flutter_reactive_ble这个库,但是在运行的时候发现一下错误 Launching lib/main.dart on AQM AL10 in debug mode... /Users/macbook/Desktop/test/flutter/my_app/android/app/src/debug/AndroidManifest.xml Err…...
Spark 的容错机制:保障数据处理的稳定性与高效性
Spark 的介绍与搭建:从理论到实践_spark环境搭建-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交:本地与集群模式全解析-CSDN博客 Spark on YARN:Spark集群模式…...
TCP可靠连接的建立和释放,TCP报文段的格式,UDP简单介绍
TCP连接的建立(三次握手) 建立连接使用的三报文 SYN 报文仅用于 TCP 三次握手中的第一个和第二个报文(SYN 和 SYN-ACK),用于初始化连接的序列号。数据传输阶段不再使用 SYN 标志。 SYN 报文通常只携带连接请求信息&a…...
LLMs之PDF:zeroX(一款PDF到Markdown 的视觉模型转换工具)的简介、安装和使用方法、案例应用之详细攻略
LLMs之PDF:zeroX(一款PDF到Markdown 的视觉模型转换工具)的简介、安装和使用方法、案例应用之详细攻略 目录 zeroX的简介 1、支持的文件类型 zeroX的安装和使用方法 T1、Node.js 版本: 安装 使用方法 使用文件 URL: 使用本地路径&…...
开源数据库 - mysql - mysql-server-8.4(gtid主主同步+ keepalived热切换)部署方案
前置条件 假设主从信息 mysqlhostport主192.168.1.13306从192.168.1.23306vip192.168.1.3 部署流程 导出测试环境表结构与数据 使用mysqldump ./mysqldump -ulzzc -p -S /tmp/mysql3306.sock --single-transaction --database lzzc > databaseLZZCxxxx.sql查看gtid号 …...
Java全栈体系路线
Java全栈体系路线 摘要 Java 是一门广泛应用于企业级开发的语言,具有强大的生态系统和丰富的工具支持。成为一名 Java 全栈开发工程师不仅需要掌握后端开发技能,还需要具备前端开发和数据库管理的能力。本文将详细介绍 Java 全栈开发的学习路线&#x…...
【Unity基础】Unity中如何导入字体?
在Unity中,不能像其他软件一样直接使用字体文件,需要通过FontAssetCreator将其转换成Texture的Asset文件,然后才能使用。 本文介绍了使用FontAssetCreator导入字体的过程,并对其参数设置进行了说明。 Font Asset Creator 是 Uni…...
使用NVIDIA GPU加速FFmpeg视频压制:完全指南
引言 在视频处理领域,FFmpeg是一个强大的工具。结合NVIDIA的硬件编码器NVENC,我们可以实现快速高效的视频压制。本文将详细解析一个实用的视频压制命令,帮助你理解每个参数的作用。 核心命令 ffmpeg -i input.mp4 -vf scale640:360 -c:v h…...
Python学习:scipy是什么?
文章目录 一、Scipy简介二、Scipy的组成部分1. 基础功能:2. 特殊函数:3. 优化:4. 积分:5. 插值:6. 信号处理:7. 图像处理:8. 统计分布:9. 空间数据结构和算法:10. 稀疏矩…...
spark的学习-05
SparkSql 结构化数据与非结构化数据 结构化数据就类似于excel表中的数据(统计的都是结构化的数据)一般都使用sparkSql处理结构化的数据 结构化的文件:JSON、CSV【以逗号分隔】、TSV【以制表符分隔】、parquet、orc 结构化的表:…...
SQL注入(SQL Injection)详解
SQL注入(SQL Injection)是一种代码注入技术,它通过在应用程序的输入字段中插入或“注入”恶意的SQL语句,从而操控后端数据库服务器执行非预期的命令。这种攻击方式常用于绕过应用程序的安全措施,未经授权地访问、修改或…...
深入解析 OpenHarmony 构建系统-2-目录结构与核心组件
引言 OpenHarmony作为一款面向全场景的分布式操作系统,其构建系统在开发过程中扮演着至关重要的角色。本文将详细介绍OpenHarmony构建系统的目录结构和核心组件,帮助开发者更好地理解和使用这一强大的工具。 目录结构概览 以下是OpenHarmony构建系统的目录结构,每个目录和…...
网络安全应急响应(归纳)
目录 一、概述二、理论 系统排查 系统基本信息 windowsLinux用户信息 WindowsLinux启动项:开机系统在前台或者后台运行的程序,是病毒等实现持久化驻留的常用方法。 WindowsLinux任务计划:由于很多计算机都会自动加载“任务计划”,…...
【网络协议栈】网络层(上)网络层的基本理解、IP协议格式、网络层分组(内附手画分析图 简单易懂)
绪论 “It does not matter how slowly you go as long as you do not stop.”。本章是自上而下的进入网络协议栈的第三个篇幅–网络层–,本章我将带你了解网络层,以及网络层中非常重要的IP协议格式和网络层的分片组装问题,后面将持续更新网…...
数据库类型介绍
1. 关系型数据库(RDBMS) 关系型数据库是最常见的一类数据库,它们通过表(Table)来存储数据,表之间通过关系(如主键和外键)来关联。 • MySQL:开源的关系型数据库管理系统&…...
一步一步从asp.net core mvc中访问asp.net core WebApi
"从asp.net core mvc中访问asp.net core WebApi"看到这个标题是不是觉得很绕口啊,但的确就是要讲一讲这样的访问。前面我们介绍了微信小程序访问asp.net core webapi(感兴趣的童鞋可以看看前面的博文有关WEBAPI的搭建),这里我们重点不关心如何…...
linux中kubectl命令使用
一.命令介绍 kubectl 是 Kubernetes 集群管理的命令行工具,用于与 Kubernetes API 交互。你可以通过它来管理和操作 Kubernetes 集群中的资源,如 Pod、Deployment、Service 等。下面是如何在不同操作系统上下载和使用 kubectl 的方法。 二.下载 kubect…...
Linux 系统结构
Linux系统一般有4个主要部分:内核、shell、文件系统和应用程序。内核、shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序、管理文件并使用系统。 1. linux内核 内核是操作系统的核心,具有很多最基本功能,它…...
ESP32-S3设备智能化升级,物联网无线AI语音交互,让生活更加便捷和有趣
在人工智能和物联网技术的推动下,无线AI语音交互技术正在成为智能设备的新选择。这种技术的发展,不仅改变了我们与设备的沟通方式,更开启了一个新的智能交互方案。 想象一下,通过简单的语音指令,就能控制家中的灯光、…...
3分钟掌握清华PPT模板:免费打造专业学术演示文稿的终极方案
3分钟掌握清华PPT模板:免费打造专业学术演示文稿的终极方案 【免费下载链接】THU-PPT-Theme 清华主题PPT模板 项目地址: https://gitcode.com/gh_mirrors/th/THU-PPT-Theme 还在为学术汇报、毕业答辩或重要演讲的PPT设计而头疼吗?清华大学视觉设计…...
目标检测:YOLOv12训练自己的数据集,手把手教学一看就会
目录 1. 环境配置 2. 数据集 2.1 网上搜索公开数据集 2.1.1 搜索引擎 2.1.2 Kaggle 2.1.3 Roboflow 2.2 自制数据集 2.2.1 Labelimg安装 2.2.2 Labelimg使用 2.3 数据集转换及划分 2.3.1 数据集VOC格式转yolo格式 2.3.2 数据集划分 3. 训练模型 3.1 创建data.yam…...
构建 AI Agent 应用商店的构想
构建 AI Agent 应用商店的构想:从“单骑救主”的工具到“生态协同”的智能枢纽关键词 AI Agent、应用商店、多Agent协作、工具调用链、Prompt工程标准化、安全沙箱、智能分发摘要 当你在凌晨2点对着一份混乱的月度财务报表焦虑时,有没有想过:…...
Unitree GO2 ROS2 SDK完整指南:5步实现四足机器人智能控制与自主导航
Unitree GO2 ROS2 SDK完整指南:5步实现四足机器人智能控制与自主导航 【免费下载链接】go2_ros2_sdk Unofficial ROS2 SDK support for Unitree GO2 AIR/PRO/EDU 项目地址: https://gitcode.com/gh_mirrors/go/go2_ros2_sdk Unitree GO2 ROS2 SDK为四足机器人…...
NRF52833开发实战:从零构建Keil工程与一键烧录
1. 环境搭建:从零准备NRF52833开发工具链 第一次接触NRF52833开发时,最头疼的就是环境配置。记得我刚开始用Keil调试蓝牙项目时,光是找齐所有安装包就花了整整两天。现在把完整工具链的获取方式和避坑要点整理给你,新手照着做半小…...
QML WebEngine与ECharts联袂:打造高性能实时数据可视化桌面应用
1. 为什么选择QMLWebEngineECharts组合? 在开发桌面端实时数据可视化应用时,我们常常面临一个关键选择:是使用原生绘图方案还是Web技术栈?我经过多个工业监控项目的实战验证,发现QMLWebEngineECharts的组合堪称黄金搭…...
如何快速安装HS2汉化补丁:完整游戏优化指南
如何快速安装HS2汉化补丁:完整游戏优化指南 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch HS2-HF Patch是HoneySelect2玩家的终极解决方案…...
终极指南:华为光猫配置解密工具深度解析与应用实践
终极指南:华为光猫配置解密工具深度解析与应用实践 【免费下载链接】HuaWei-Optical-Network-Terminal-Decoder 项目地址: https://gitcode.com/gh_mirrors/hu/HuaWei-Optical-Network-Terminal-Decoder 华为光猫配置解密工具(HuaWei-Optical-Ne…...
从Andru充电器看情感化硬件设计:EDA工具如何实现功能与体验融合
1. 项目概述:从“无聊”到“有趣”的设计哲学 昨天,我还在想,给手机、相机充个电能有什么花样?无非就是找个充电头,插上线,然后等着。这大概是世界上最“无聊”但又最必需的任务之一了。如果有人跑过来跟我…...
基于MCP协议与Playwright的AI智能体网页抓取工具部署与实战
1. 项目概述:一个为AI智能体打造的“网页抓取工具箱” 如果你正在开发或使用基于MCP(Model Context Protocol)的AI智能体,并且经常需要让它们从网页上获取结构化数据,那么你很可能已经遇到了一个核心痛点: …...
