C++网络程序设计
在C++网络编程
中,使用Berkeley Sockets API
是一种常见的方法来实现跨平台的TCP通信。Berkeley Sockets API
最初是在UNIX
系统上开发的,但它已经被广泛移植到其他操作系统,包括Windows
。
示例代码
client.cpp
#include <iostream>
#include <cstring>#ifdef _WIN32
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib") // Winsock 库
typedef int socklen_t;
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#define closesocket close
#endifconst int PORT = 8080;
const int BUFFER_SIZE = 1024;void initialize_sockets()
{
#ifdef _WIN32WSADATA wsa;if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0){std::cerr << "Failed to initialize Winsock" << std::endl;exit(EXIT_FAILURE);}
#endif
}void cleanup_sockets()
{
#ifdef _WIN32WSACleanup();
#endif
}int main()
{initialize_sockets();int server_fd, new_socket;struct sockaddr_in server_addr, client_addr;char buffer[BUFFER_SIZE] = {0};// 创建套接字server_fd = socket(AF_INET, SOCK_STREAM, 0);if (server_fd == -1){std::cerr << "Socket creation failed" << std::endl;cleanup_sockets();return -1;}// 初始化服务器地址结构server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = INADDR_ANY;server_addr.sin_port = htons(PORT);// 绑定套接字到端口if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0){std::cerr << "Bind failed" << std::endl;closesocket(server_fd);cleanup_sockets();return -1;}// 监听连接if (listen(server_fd, 3) < 0){std::cerr << "Listen failed" << std::endl;closesocket(server_fd);cleanup_sockets();return -1;}std::cout << "Server listening on port " << PORT << std::endl;socklen_t addr_len = sizeof(client_addr);// 接受客户端连接new_socket = accept(server_fd, (struct sockaddr *)&client_addr, &addr_len);if (new_socket < 0){std::cerr << "Accept failed" << std::endl;closesocket(server_fd);cleanup_sockets();return -1;}// 读取客户端消息int valread = recv(new_socket, buffer, BUFFER_SIZE, 0);if (valread > 0){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;// 关闭套接字closesocket(new_socket);closesocket(server_fd);cleanup_sockets();return 0;
}
server.cpp
#include <iostream>
#include <cstring>#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib") // Winsock 库
typedef int socklen_t;
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#define closesocket close
#endif#pragma comment(lib, "ws2_32.lib") // 确保链接 Winsock 库int main()
{// 初始化 WinsockWSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){std::cerr << "Failed to initialize Winsock." << std::endl;return -1;}// 创建套接字int server_fd = socket(AF_INET, SOCK_STREAM, 0);if (server_fd == INVALID_SOCKET){std::cerr << "Socket creation failed." << std::endl;WSACleanup();return -1;}// 设置地址结构struct sockaddr_in address;address.sin_family = AF_INET; // 使用 IPv4 协议address.sin_addr.s_addr = INADDR_ANY; // 允许接受来自任何地址的连接address.sin_port = htons(8080); // 监听8080端口// 绑定套接字if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0){std::cerr << "Bind failed." << std::endl;closesocket(server_fd);WSACleanup();return -1;}// 监听套接字if (listen(server_fd, 3) < 0){std::cerr << "Listen failed." << std::endl;closesocket(server_fd);WSACleanup();return -1;}std::cout << "Listening on port 8080..." << std::endl;// 接受连接int addrlen = sizeof(address);int client_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen); // 接受连接if (client_socket == INVALID_SOCKET){std::cerr << "Accept failed" << std::endl;closesocket(server_fd);WSACleanup();return -1;}const char *message = "Hello from server";send(client_socket, message, strlen(message), 0); // 发送数据std::cout << "Message sent to client" << std::endl;// 关闭通信套接字closesocket(client_socket);// 关闭监听套接字closesocket(server_fd);// 清理 WinsockWSACleanup();return 0;
}
通过系统API
示例代码实现了无关操作系统(Windows 和 Linux)的网络通信,下面我们将对代码从上到下进行逐步解释(只分析服务器端代码,客户端代码类似):
跨平台开发的问题
Windows
和Linux
都提供了各自用于网络通信的API
,其中大部分都一致,但是还是有一些函数名和头文件名等细节上的不同,为了能够做到跨平台开发,需要开发者注意到这些细节。
- 头文件:Linux 和 Windows 的头文件不同,Windows 需要包含
Winsock2.h
和初始化Winsock
。- 网络库的链接:在 Windows 上需要链接
ws2_32.lib
。- 系统特有函数:如
close()
和closesocket()
的差异。
在c++中,可以通过宏处理
的方法,来规范化不同系统间的差异,编写出一套通用的代码。
// 处理跨平台的头文件和函数差异
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib") // Winsock 库
typedef int socklen_t;
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#define closesocket close
#endif
ws2_32.lib
是 Winsock 库
的静态链接库文件,Winsock
是 Windows 操作系统提供的用于网络通信的接口。通过在代码中包含 #pragma comment(lib, "ws2_32.lib")
,编译器会自动链接这个库,使得你的程序可以使用 Winsock 提供的网络编程功能,如创建套接字、绑定端口、监听连接等。
主函数部分
WSADATA wsaData;
我们点进去看WSADATA
结构体的定义如下:
发现,宏判断上下几乎没有区别,只是顺序改变。那么这么做是为了什么?
为了提高效率,实现内存对齐
在不同架构的系统中(如32位和64位系统)调整结构体成员的定义顺序主要是为了优化内存对齐和减少内存占用。这种优化在性能敏感的应用中尤为重要。以下是具体原因:
- 内存对齐:
- 处理器访问内存时具有特定的对齐要求。例如,在某些处理器上,访问4字节数据时,其地址必须是4的倍数。
unsigned short
是2字节的,而char*
通常是4字节(在32位系统上)或8字节(在64位系统上)。- 如果结构体成员的定义顺序不当,可能会导致结构体中出现“填充”字节(即未使用的字节),以满足处理器的对齐要求。这会增加结构体的大小,从而浪费内存。
- 内存占用:
- 在64位系统中,
char*
是8字节的。如果char*
之前的成员是unsigned short
(2字节),为了对齐char*
,编译器会在unsigned short
之后插入6字节的填充字节。- 通过调整成员的顺序,可以减少这些填充字节的数量,从而减小结构体的总大小,提高内存使用效率。
具体到你提供的代码:
64位系统:
unsigned short iMaxSockets; unsigned short iMaxUdpDg; char *lpVendorInfo;
iMaxSockets
和iMaxUdpDg
是两个unsigned short
,总共4字节。lpVendorInfo
是一个char*
,在64位系统中是8字节。- 这样的顺序可以避免在
lpVendorInfo
前面插入填充字节。非64位系统:
char szDescription[WSADESCRIPTION_LEN+1]; char szSystemStatus[WSASYS_STATUS_LEN+1]; unsigned short iMaxSockets; unsigned short iMaxUdpDg; char *lpVendorInfo;
szDescription
和szSystemStatus
是字符数组,通常以字节对齐。unsigned short
在32位系统中是2字节,排列在字符数组之后可以减少填充字节的使用。lpVendorInfo
在32位系统中是4字节的指针,排列在两个unsigned short
之后可以更好地利用内存对齐。通过调整结构体成员的顺序,可以减少内存中的填充字节,提高内存使用效率,从而优化程序的性能。
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{std::cerr << "Failed to initialize Winsock." << std::endl;return -1;
}
WSAStartup
函数:
作用: 初始化Winsock库,使其可以使用。
参数:
MAKEWORD(2, 2)
:这是一个宏,用于创建一个16位的版本号。MAKEWORD
函数将两个8位的值组合成一个16位的值。在这里,2, 2
表示Winsock的版本2.2。使用
MAKEWORD(2, 2)
将这两个值组合成一个16位的值,表示Winsock版本2.2。具体来说:
2
(低位字节)表示次版本号。- 后一个
2
(高位字节)表示主版本号。通过这种方式,
MAKEWORD(2, 2)
生成的值是0x0202
,这正是Winsock版本2.2的表示。
&wsaData
:指向WSADATA
结构体的指针,用于接收关于Winsock实现的信息。返回值:如果初始化成功,返回0;如果失败,返回一个错误代码。
// 创建套接字int server_fd = socket(AF_INET, SOCK_STREAM, 0);if (server_fd == INVALID_SOCKET){std::cerr << "Socket creation failed." << std::endl;WSACleanup();return -1;}
socket
函数:
- 作用: 创建一个新的套接字。
- 参数:
AF_INET
:指定地址族为IPv4。(改为AF_INET就是IPv6
)SOCK_STREAM
:指定套接字类型为TCP流套接字。(SOCK_DGRAM是DUP流套接字
)0
:指定协议为默认协议(对于TCP,通常是IP协议)。- 返回值:如果成功,返回一个
套接字描述符
;如果失败,返回INVALID_SOCKET
。唯一标识套接字:
- 每个套接字在创建时都会被分配一个唯一的套接字描述符。这个描述符在整个程序中用于引用该套接字,确保所有的网络操作(如绑定、监听、连接、发送和接收数据等)都是针对正确的套接字进行的。
INVALID_SOCKET
常量:
- 在Winsock中,
INVALID_SOCKET
是一个特殊的值,用于表示套接字创建失败。它通常定义为-1。- 错误处理:
- 如果
socket
函数返回INVALID_SOCKET
,表示套接字创建失败。此时,程序输出错误信息到标准错误流(std::cerr
),并调用WSACleanup()
函数来清理Winsock资源。WSACleanup()
函数用于释放Winsock库占用的资源,确保程序不会因未释放资源而导致内存泄漏或其他问题。- 最后,程序返回-1,表示异常退出。
// 设置地址结构
struct sockaddr_in address;
address.sin_family = AF_INET; // 使用 IPv4 协议
address.sin_addr.s_addr = INADDR_ANY; // 允许接受来自任何地址的连接
address.sin_port = htons(8080); // 监听8080端口
// 绑定套接字
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0)
{std::cerr << "Bind failed." << std::endl;closesocket(server_fd);WSACleanup();return -1;
}
bind
函数:
- 作用: 将套接字与特定的网络地址和端口关联起来。
- 参数:
server_fd
:套接字描述符,表示要绑定的套接字。(struct sockaddr *)&address
:指向sockaddr
结构体的指针,该结构体包含了要绑定的地址信息。sockaddr
是一个通用的地址结构体,可以转换为特定的地址结构体(如sockaddr_in
用于IPv4,sockaddr_in6
用于IPv6)。sizeof(address)
:address
结构体的大小,确保bind
函数知道要处理的地址信息的长度。- 返回值:如果绑定成功,返回0;如果失败,返回-1。
- 错误处理:
- 如果
bind
函数返回-1,表示绑定失败。此时,程序输出错误信息到标准错误流(std::cerr)
,并执行以下操作:
- 调用
closesocket(server_fd)
关闭套接字,释放与套接字相关的资源。- 调用
WSACleanup()
清理Winsock库,释放Winsock库占用的资源。- 返回-1,表示程序异常退出。
// 监听套接字
if (listen(server_fd, 3) < 0)
{std::cerr << "Listen failed." << std::endl;closesocket(server_fd);WSACleanup();return -1;
}
std::cout << "Listening on port 8080..." << std::endl;
listen
函数:
- 作用: 使套接字进入监听状态,以便接受客户端的连接请求。
- 参数:
server_fd
:套接字描述符,表示要监听的套接字。这个套接字应该已经通过socket()
函数创建,并且已经通过bind()
函数绑定到特定的网络地址和端口。3
:表示监听队列的长度,即服务器可以同时处理的最大连接请求数量。在这个例子中,服务器可以同时处理3个连接请求。如果新的连接请求到来时队列已满,客户端将收到连接拒绝的错误。- 返回值:如果监听成功,返回0;如果失败,返回-1。
- 错误处理:
- 如果
listen
函数返回-1,表示监听失败。此时,程序输出错误信息到标准错误流(std::cerr)
,并执行以下操作:
- 调用
closesocket(server_fd)
关闭套接字,释放与套接字相关的资源。- 调用
WSACleanup();
函数清理Winsock库(在Windows平台上),释放Winsock库占用的资源。- 返回-1,表示程序异常退出。
// 接受连接
int addrlen = sizeof(address);
int client_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen); // 接受连接
if (client_socket == INVALID_SOCKET)
{std::cerr << "Accept failed" << std::endl;closesocket(server_fd);WSACleanup();return -1;
}
accept
函数:
- 作用: 从监听套接字中接受一个连接请求,并创建一个新的套接字用于与客户端通信。
- 参数:
server_fd
:监听套接字的描述符。这个套接字应该已经通过socket()
函数创建,并且已经通过bind()
函数绑定到特定的网络地址和端口,并且已经调用listen()
函数进入监听状态。(struct sockaddr *)&address
:指向sockaddr
结构体的指针,用于接收客户端的地址信息。sockaddr
是一个通用的地址结构体,可以转换为特定的地址结构体(如sockaddr_in
用于IPv4)。(socklen_t *)&addrlen
:指向socklen_t
类型的指针,表示客户端地址结构体的大小。accept
函数会更新这个值为实际接收到的客户端地址的大小。- 返回值:如果接受连接成功,返回一个新的套接字描述符,用于与客户端进行通信;如果失败,返回
INVALID_SOCKET
。- 错误处理:
- 如果
accept
函数返回INVALID_SOCKET
,表示接受连接失败。此时,程序输出错误信息到标准错误流(std::cerr)
,并执行以下操作:
- 调用
closesocket(server_fd)
关闭监听套接字,释放与套接字相关的资源。- 调用
WSACleanup()
函数清理Winsock库,释放Winsock库占用的资源。- 返回-1,表示程序异常退出。
const char *message = "Hello from server";
send(client_socket, message, strlen(message), 0); // 发送数据
std::cout << "Message sent to client" << std::endl;
发送信息调用
send
函数,参数分别是
accept
函数返回的(用于通信的通信套接字)client_socket
- 字符串
message
- 字符串的长度
flag标志位
send
函数的flags
参数
send
函数的原型如下:ssize_t send(int sockfd, const void *buf, size_t len, int flags);
sockfd
:套接字描述符,表示要发送数据的套接字。buf
:指向要发送的数据缓冲区的指针。len
:要发送的数据的长度(以字节为单位)。flags
:控制发送操作的标志位。可以是以下标志的组合:常用的
flags
标志位
0
:默认值,表示没有特殊标志。MSG_DONTWAIT
:在非阻塞套接字上,如果数据无法立即发送,则立即返回,而不是等待。在阻塞套接字上,这个标志通常没有效果。MSG_OOB
:发送带外数据(out-of-band data)。带外数据是一种特殊的数据传输机制,用于传输紧急数据。MSG_NOSIGNAL
:不生成信号。在某些情况下,发送操作可能会导致信号的生成(如SIGPIPE
),这个标志可以抑制这些信号。MSG_EOR
:指示数据包的结束。对于某些协议(如记录协议),这个标志可以用来指示数据包的结束。MSG_DONTROUTE
:不使用路由表,直接将数据发送到本地网络。这个标志通常用于本地网络通信。
// 关闭通信套接字
closesocket(client_socket);
// 关闭监听套接字
closesocket(server_fd);
// 清理 Winsock
WSACleanup();
Boost.Asio
特点:
- 跨平台:Boost.Asio 是跨平台的库,可以很容易地在 Windows、Linux、macOS 等操作系统上使用。
- 高性能:支持异步和同步操作,能够处理大量的并发连接。
- 灵活性:提供多种网络协议和传输方式的支持,包括 TCP、UDP、ICMP 等。
- 社区支持:作为 Boost 库的一部分,拥有庞大的用户基础和丰富的文档资源。
- 易于集成:可以方便地与现有的 C++ 项目集成。
示例:
#include <boost/asio.hpp>
#include <iostream>using boost::asio::ip::tcp;int main() {try {boost::asio::io_context io_context;tcp::resolver resolver(io_context);tcp::resolver::results_type endpoints =resolver.resolve("example.com", "http");tcp::socket socket(io_context);boost::asio::connect(socket, endpoints);boost::asio::streambuf request;std::ostream request_stream(&request);request_stream << "GET / HTTP/1.1\r\n";request_stream << "Host: example.com\r\n";request_stream << "Accept: */*\r\n";request_stream << "Connection: close\r\n\r\n";boost::asio::write(socket, request);boost::asio::streambuf response;boost::asio::read_until(socket, response, "\r\n");std::istream response_stream(&response);std::string http_version;response_stream >> http_version;unsigned int status_code;response_stream >> status_code;std::string status_message;std::getline(response_stream, status_message);if (!response_stream || http_version.substr(0, 5) != "HTTP/") {std::cerr << "Invalid response\n";return 1;}if (status_code != 200) {std::cerr << "Response returned with status code ";std::cerr << status_code << "\n";return 1;}std::cout << "Response:\n";std::cout << &response;} catch (std::exception& e) {std::cerr << "Exception: " << e.what() << "\n";}return 0;
}
相关文章:
C++网络程序设计
在C网络编程中,使用Berkeley Sockets API是一种常见的方法来实现跨平台的TCP通信。Berkeley Sockets API最初是在UNIX系统上开发的,但它已经被广泛移植到其他操作系统,包括Windows。 示例代码 client.cpp #include <iostream> #incl…...
【快速实践】深度学习 -- 数据曲线平滑化
希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦 欢迎关注、订阅专栏 【深度学习从 0 到 1】谢谢你的支持! 在观察数据结果时,我们通常希望获得整体趋…...
【强化学习】演员评论家Actor-Critic算法(万字长文、附代码)
📢本篇文章是博主强化学习(RL)领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅…...
Kubernetes Gateway API-5-后端协议和网关基础设置标签
1 后端协议 自 v1.2.0 开始支持 并非所有网关API实现都支持自动协议选择。在某些情况下,协议在没有明确选择加入的情况下被禁用。 当 Route 的后端引用Kubernetes Service 时,应用程序开发人员可以使用 ServicePort appProtocol 字段指定协议。 例如…...
鸿蒙 ArkUI实现地图找房效果
常用的地图找房功能,是在地图上添加区域、商圈、房源等一些自定义 marker,然后配上自己应用的一些筛选逻辑构成,在这里使用鸿蒙 ArkUI 简单实现下怎么添加区域/商圈、房源等 Marker. 1、开启地图服务 在华为开发者官网,注册应用&…...
前后端分离架构设计与实现:构建现代Web应用的基石
前后端分离架构设计与实现:构建现代Web应用的基石 引言 随着互联网技术的发展,Web应用变得越来越复杂和多样化。传统的单体式架构难以满足快速迭代、团队协作以及性能优化的需求。前后端分离架构应运而生,它不仅提高了开发效率,…...
【51单片机】02LED流水灯实验
点亮你的LED 一、点亮第一个LED1.GPIO介绍2.P1、P2、P3端口 二、LED实验2.尝试点亮LED3.LED流水灯4.利用库函数实现流水灯的移动 一、点亮第一个LED 1.GPIO介绍 这块内容这里可以做简单的了解,与数电知识强相关。后续可以再回过头来学习 GPIO (general purpose in…...
【简博士统计学习方法】第1章:4. 模型的评估与选择
4. 模型的评估与选择 4.1 训练误差与测试误差 假如存在样本容量为 N N N的训练集,将训练集送入学习系统可以训练学习得到一个模型,我们将这么模型用决策函数的形式表达,也就是 y f ^ ( x ) y\hat{f}(x) yf^(x),关于模型的拟合…...
GitLab创建用户,设置访问SSH Key
继上一篇 Linux Red Hat 7.9 Server安装GitLab-CSDN博客 安装好gitlab,启用管理员root账号后,开始创建用户账户 1、创建用户账户 进入管理后台页面 点击 New User 输入用户名、邮箱等必填信息和登录密码 密码最小的8位,不然会不通过 拉到…...
flutter 专题二十四 Flutter性能优化在携程酒店的实践
Flutter性能优化在携程酒店的实践 一 、前言 携程酒店业务使用Flutter技术开发的时间快接近两年,这期间有列表页、详情页、相册页等页面使用了Flutter技术栈进行了跨平台整合,大大提高了研发效率。在开发过程中,也遇到了一些性能相关问题和…...
RAFT:随机退火森林
RAFT:随机退火森林 RAFT(Randomized Annealed Forests)是一种机器学习算法,主要用于分类和回归任务。以下是对它的介绍及原理举例说明: 一、RAFT简介 RAFT是一种基于随机森林的集成学习方法,它结合了随机森林的优点和退火算法的思想。随机森林通过构建多个决策树并综…...
上下游服务间解耦的技术与管理
一、解耦为何至关重要 在当今软件研发的复杂生态中,耦合问题如影随形,困扰着众多开发者与企业。当多个模块、系统或团队紧密交织,相互依赖程度不断攀升,仿佛一张错综复杂的网,牵一发而动全身。就拿电商系统来说&#…...
[桌面运维]windows自动设置浅深色主题
设置自动浅色/深色主题 我看很多up主的教程过于繁琐,需要添加四个功能,并且有些还不能生效! 大多数都是教程: 自动任务栏浅色 add HKCUSOFTWAREMicrosoftWindowsCurrentVersionThemesPersonalize/v SystemUsesLightTheme /t …...
【Spring】Spring DI(依赖注入)详解——注入参数的细节处理-内部Bean的注入
引言 在现代Java开发中,Spring框架已经成为了构建企业级应用的标准工具之一。Spring的核心特性之一就是依赖注入(Dependency Injection,DI),它通过将对象的依赖关系从代码中解耦出来,提升了代码的可维护性…...
Docker: 教程07 - ( 如何对 Docker 进行降级和升级)
如果我们使用 docker 来管理容器,那么保持 docker 引擎的更新将会是十分重要的,这一篇文章我们将会讨论如何对Docker 进行降级和升级。 准备工作 - docker 环境 我们需要拥有一个安装好 docker 的运行环境。 如果你需要了解如何安装 docker 可以通过如…...
CV-LLM经典论文解读|VTimeLLM: Empower LLM to Grasp Video MomentsVTimeLLM:赋能大语言模型理解视频片段
论文标题 VTimeLLM: Empower LLM to Grasp Video Moments VTimeLLM:赋能大语言模型理解视频片段 论文链接: VTimeLLM: Empower LLM to Grasp Video Moments论文下载 论文作者 Bin Huang, Xin Wang, Hong Chen, Zihan Song, Wenwu Zhu (Tsinghua Un…...
新手学习yolov8目标检测小记2--对比实验中经典模型库MMDetection使用方法(使用自己的数据集训练,并转换为yolo格式评价指标)
一、按照步骤环境配置 pip install timm1.0.7 thop efficientnet_pytorch0.7.1 einops grad-cam1.4.8 dill0.3.6 albumentations1.4.11 pytorch_wavelets1.3.0 tidecv PyWavelets -i https://pypi.tuna.tsinghua.edu.cn/simple pip install -U openmim -i https://pypi.tuna.t…...
Kubernetes开发环境minikube | 开发部署apache tomcat web单节点应用
minikube是一个主要用于开发与测试Kubernetes应用的运行环境 本文主要描述在minikube运行环境中部署J2EE tomcat web应用 minikube start --force minikube status 如上所示,在Linux中启动minikube运行环境 service docker start docker version service docker …...
浙江安吉成新的分布式光伏发电项目应用
摘 要:分布式光伏发电站是指将光伏发电组件安装在用户的建筑物屋顶、空地或其他适合的场地上,利用太阳能进行发电的一种可再生能源利用方式,与传统的大型集中式光伏电站相比,分布式光伏发电具有更灵活的布局、更低的建设成本和更高…...
Git - 记录一次由于少输入了一个命令导致的更改丢失
Git - 记录一次由于少输入了一个参数导致的更改丢失 前言 某晚我激情开发了几个小时,中途没有进行commit存档。准备睡觉时,我想创建一个新的分支并将今晚所有更改提交到新分支上(似乎应该开发时候就创建?)。 然后因…...
【Nginx】设置https和http同时使用同一个端口访问
以下是一个同时使用 HTTP 和 HTTPS 并通过 8070 端口的配置示例: server {listen 8070;server_name your_domain.com;location / {root /var/www/html;index index.html;} }server {listen 8070 ssl;server_name your_domain.com;# SSL 证书和私钥的路径ssl_certif…...
Vue 组件开发:构建高效可复用的 UI 构建块
在现代前端开发中,Vue.js 凭借其简洁的 API、渐进式框架设计和强大的生态系统,已经成为众多开发者的首选。Vue 组件化开发是其核心特性之一,它允许我们将复杂的 UI 拆分成多个独立、可复用的组件,从而提高代码的可维护性和可扩展性…...
【Uniapp-Vue3】v-if条件渲染及v-show的选择对比
如果我们想让元素根据响应式变量的值进行显示或隐藏可以使用v-if或v-show 一、v-show 另一种控制显示的方法就是使用v-show,使用方法和v-if一样,为true显示,为false则不显示。 二、v-if v-if除了可以像v-show一样单独使用外,还…...
浏览器报错:您的连接不是私密连接,Kubernetes Dashboard无法打开
问题描述 部署完成Kubernetes Dashboard后,打开HTTPS的web页面,Chrome和Edge浏览器都无法正常加载页面,会提示您的连接不是私密连接的报错。 原因: 浏览器不信任这些自签名的ssl证书,为了…...
asp.net core 属性路由和约定路由
在 ASP.NET Core 中,Web API 中的路由(Route)用于确定客户端请求的 URL 与服务器端处理逻辑之间的映射关系。路由机制在 Web API 的开发中非常重要,它帮助定义和管理不同请求路径如何触发特定的控制器和操作方法。 1. 路由概述 …...
机器学习之模型评估——混淆矩阵,交叉验证与数据标准化
目录 混淆矩阵 交叉验证 数据标准化 0-1标准化 z 标准化 混淆矩阵 混淆矩阵(Confusion Matrix)是一种用于评估分类模型性能的工具。 它是一个二维表格,其中行表示实际的类别,列表示模型预测的类别。 假设我们有一个二分类问题&…...
Java实现UDP与TCP应用程序
三、Java实现UDP应用程序 3.1 InetAddress类 java.net.InteAddress类是用于描述IP地址和域名的一个Java类; 常用方法如下: public static InetAddress getByName(String host):根据主机名获取InetAddress对象public String getHostName()…...
[python3]Excel解析库-calamine,10倍openpyxl性能
calamine 是一个用于读取多种电子表格格式(如 Excel、LibreOffice Calc 等)的 Python 库。它支持 .xls, .xlsx, .ods 和 .csv 文件格式,提供了简单易用的 API 来加载和处理电子表格数据。calamine 的一大特点是它的轻量级和高效性,…...
Clisoft SOS设置Server和Project
Clisoft SOS设置Server和Project 一、关于SOS Servers、Clients、Projects和Work Areas 以下三个图是官方文档中介绍的三种情况 图1:带有两个客户端的SOS服务器 图2:使用本地缓存服务器 图3:远程设计团队的缓存服务器 因为SOS软件需要…...
基于FPGA的出租车里程时间计费器
基于FPGA的出租车里程时间计费器 功能描述一、系统框图二、verilog代码里程增加模块时间增加模块计算价格模块上板视频演示 总结 功能描述 (1);里程计费功能:3公里以内起步价8元,超过3公里后每公里2元,其中…...
AnaConda下载PyTorch慢的解决办法
使用Conda下载比较慢,改为pip下载 复制下载链接到迅雷下载 激活虚拟环境,安装whl,即可安装成功 pip install D:\openai.wiki\ChatGLM2-6B\torch-2.4.1cu121-cp38-cp38-win_amd64.whl...
Hello 2025(A-C)
补题链接:Dashboard - Hello 2025 - Codeforces A. MEX Table 思路 除了含0的列和行其他的都是0,输出max(n,m)1即可 代码 #include<bits/stdc.h> using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); co…...
Burpsuite20241102macM1版安装
1、安装jdk11 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" brew update brew install openjdk11 echo export PATH"/opt/homebrew/opt/openjdk11/bin:$PATH" >> ~/.zshrc source ~/.zshrc j…...
jenkins入门10--自动化构建
build periodically:设定类似cron周期性时间触发构建 * * * * * (五颗星,中间用空格隔开) 第一颗表示分钟,取值0~59 第二颗表示小时,取值0~23 第三颗表示一个月的第几天,取值1~31 第四颗表示第几月…...
Java基础概念
自动装箱 Integer i 10; //装箱 int n i; //拆箱 普通数据类型:直接在栈内存中分配空间,存储的是具体的值。包装类:作为对象在堆内存中分配空间。包装类实际上是对普通数据类型的封装,每个包装类都包含了对应的数据类…...
57.在 Vue 3 中使用 OpenLayers 点击选择 Feature 设置特定颜色
在 Web 开发中,地图应用是非常常见的需求,而 OpenLayers 是一个非常强大的地图库,它提供了丰富的地图操作功能。今天,我们将一起学习如何在 Vue 3 中结合 OpenLayers 使用点击事件来选择地图上的 Feature,并设置特定的…...
HTML——61. 单行文本框和密码输入框(主讲input元素的type属性)
<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>单行文本框和密码输入框</title></head><body><!--input元素的type属性:(必须要有)--> <!--单行文本框:1.type"text"2.可…...
h264之多视点mvc编码及解码过程(JMVC平台举例)
h264标准参考平台JMVC是针对MVC标准的,JMVC支持多视点编码、合流、多视点解码操作。可以利用JMVC生成h264 mvc码流和解码。 JMVC的下载地址是:jvet / JMVC GitLabH.264/AVC multi-view coding (MVC) extension JMVC reference softwarehttps://vcgit.hh…...
深度学习blog-深刻理解线性变换和矩阵
深度学习中避免不了矩阵运算,或者张量(其实是矩阵数组)运算。卷积是矩阵加、乘法,注意力也是一样。本质都一样,所谓注意力,卷积、滤波,是对不必了解数学的人说的,底层都是矩阵运算&a…...
C语言 扫雷程序设计
目录 1.main函数 2.菜单打印menu函数 3.游戏game函数 4.宏定义 5.界面初始化 6.打印界面 7.设置雷 8.统计排查坐标周围雷的个数 9.排查雷 10.总代码 test.c代码 game.h代码 game.c代码 结语: 一个简单的扫雷游戏,通过宏定义可以修改行列的…...
[笔记] Jenkins 安装与配置全攻略:Ubuntu 从零开始搭建持续集成环境
随着 DevOps 流程的普及,持续集成(CI)和持续交付(CD)已成为现代软件开发中不可或缺的一部分。Jenkins 作为一款开源的自动化服务器,广泛应用于 CI/CD 管道的构建与管理。它不仅支持多种编程语言和工具链&am…...
【51单片机零基础-chapter3:按键:独立按键|||附带常见C语句.逻辑运算符】
将unsigned char var0;看作沟通二进制和十进制的桥梁 var是8位,初始为0000 0000; 同时可以进行十进制的运算 逻辑运算 位运算 & 按位与(有0则0) | 按位或(有1则1) ~ 按位非 ^ 按位异或(相同则1,不同为0) <<按位左移 >>按位右移 位运算符解释: 0011 1100 <&…...
深入浅出:深层网络处理技术的教学指南
引言 在人工智能的浪潮中,深层网络处理技术(Deep Learning)无疑是最耀眼的明星之一。无论是图像识别、自然语言处理,还是语音识别,深层网络都展现出了强大的能力。然而,对于初学者来说,深层网络…...
深入浅出Node.js-1(node.js入门)
全新专栏带你快速掌握node.js Node.js入门 html,css,js 30年了 nodejs环境 09年出现 15年 nodejs为我们解决了2个方面的问题: 【锦上添花】让我们前端工程师拥有了后端开发能力(开接口,访问数据库) - 大公司BFF(5…...
Django的runserver
当年执行 python manage runserver命令时 1. 先执行 runserver 中的 handle方法 2. 执行 self.run()方法 3. 执行 self.inner_run() 3.1 inner_run 下 run方法的封装 3.1.1 接着看 handle 怎么来的 封装了一个方法 接着找返回函数 3.1.2在 basehttp 下 3.1.3 get_wsgi_appl…...
MySQL 存储引擎
InnoDB InnoDB是MySQL的默认存储引擎,自MySQL 5.5版本起开始使用。它提供了具有提交、回滚和崩溃恢复能力的事务安全(ACID兼容)存储引擎。 主要特性: 事务支持:完全支持ACID(原子性、一致性、隔离性、持久…...
React知识盲点——组件通信、性能优化、高级功能详解(大纲)
组件通信 React 组件通信详解 在 React 中,组件通信是一个核心概念,主要指的是如何让不同的组件共享和传递数据。React 提供了多种机制来实现组件间的数据传递和状态共享。以下是几种常见的组件通信方式,包括:父子组件通信&…...
Maven 详细配置:Maven 项目 POM 文件解读
Maven 是 Java 开发领域中广泛使用的项目管理和构建工具,通过其核心配置文件——POM(Project Object Model)文件,开发者能够定义项目的基本信息、依赖关系、插件配置以及构建生命周期等关键要素。POM 文件不仅是 Maven 项目的核心…...
selenium
pythonselenium selenium是一个第三方库,python有很多库; 1、什么是ui自动化? 通过模拟手工操作用户ui页面的方式,用代码去实现自动化操作和验证的行为。 2、ui自动化的优点? (1)解决重复性的功能测试…...
网络安全:设备原理与操作
设备型号概述 网络安全企业有哪些? 国外:思科,Juniper,惠普,3Com,。。。。 国内:华为,中性,锐捷,蓝盾,绿盟,山石网科,36…...