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

socket 收发TCP/UDP

一、c++

个人测试记录,有问题还请指出,谢谢

参考:C++开发基础之网络编程WinSock库使用详解TCP/UDP Socket开发_c++ udp使用什么库-CSDN博客

代码中Logger测试见文章: c++中spdlog的使用/python中logger的使用-CSDN博客

1、main.cpp

收发TCP信号:

#include <iostream>
#include <thread>
#include <vector>#include "Logger.h"
#include "SocketManager.h"#pragma warning(disable:4996)int main() {initLogger();SocketManager socket_manager;// 使用 std::thread 并传递成员函数的指针和对象实例的引用std::thread t1(&SocketManager::get_from_tcp, &socket_manager, 11100);// std::thread t2(&SocketManager::get_from_udp, &socket_manager, 11111);std::thread t3(&SocketManager::send_to_tcp, &socket_manager, "123456", "127.0.0.1", 11100);// std::thread t4(&SocketManager::send_to_udp, &socket_manager, "123456", "127.0.0.1", 11111);t1.detach();// t2.detach();t3.detach();// t4.detach();Sleep(6000000);return 0;
}

 运行结果如下:

 收发UDP信号:

#include <iostream>
#include <thread>
#include <vector>#include "Logger.h"
#include "SocketManager.h"#pragma warning(disable:4996)int main() {initLogger();SocketManager socket_manager;// 使用 std::thread 并传递成员函数的指针和对象实例的引用// std::thread t1(&SocketManager::get_from_tcp, &socket_manager, 11100);std::thread t2(&SocketManager::get_from_udp, &socket_manager, 11111);// std::thread t3(&SocketManager::send_to_tcp, &socket_manager, "123456", "127.0.0.1", 11100);std::thread t4(&SocketManager::send_to_udp, &socket_manager, "123456", "127.0.0.1", 11111);// t1.detach();t2.detach();// t3.detach();t4.detach();Sleep(6000000);return 0;
}

 运行结果如下:

2、SocketManager.h

// #pragma once  // 为确保在不同编译环境中使用,可以使用#define的方法
#ifndef	SOCKETMANAGER_H
#define SOCKETMANAGER_H#include <iostream>
#include <stdio.h>
#include <winsock2.h>
#include <string>
#include "Logger.h"#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996)std::string asciiToHex(const std::string& asciiStr); // 将ascii码转为十六进制class SocketManager {
public:SocketManager();~SocketManager();void initialization();  // 初始化套接字库void get_from_udp(int);   // 从客户端接收发来的udp信息void get_from_tcp(int); // 从客户端接收发来的tcp信息void send_to_tcp(std::string, std::string, int);  // 向服务端发送tcp信息void send_to_udp(std::string, std::string, int);  // 向服务端发送udp信息private://定义服务端套接字,接受请求套接字SOCKET ListenSocket_UDP_get;SOCKET ListenSocket_TCP_get;SOCKET SendSocket_UDP_to;SOCKET SendSocket_TCP_to;//服务端/客户端地址SOCKADDR_IN service_UDP_get;SOCKADDR_IN service_TCP_get;SOCKADDR_IN service_UDP_to;SOCKADDR_IN service_TCP_to;
};#endif  // SOCKETMANAGER_H

3、SocketManager.cpp

#include "SocketManager.h"SocketManager::SocketManager() {ListenSocket_UDP_get = INVALID_SOCKET;ListenSocket_TCP_get = INVALID_SOCKET;SendSocket_UDP_to = INVALID_SOCKET;SendSocket_TCP_to = INVALID_SOCKET;
}SocketManager::~SocketManager() {if (ListenSocket_UDP_get != INVALID_SOCKET) {closesocket(ListenSocket_UDP_get);WSACleanup();}if (ListenSocket_TCP_get != INVALID_SOCKET) {closesocket(ListenSocket_TCP_get);WSACleanup();}if (SendSocket_UDP_to != INVALID_SOCKET) {closesocket(SendSocket_UDP_to);WSACleanup();}if (SendSocket_TCP_to != INVALID_SOCKET) {closesocket(SendSocket_TCP_to);WSACleanup();}
}void SocketManager::get_from_udp(int port) {// 初始化套接字库initialization();// 创建套接字ListenSocket_UDP_get = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);if (ListenSocket_UDP_get == INVALID_SOCKET) {logger->error("创建套接字失败:" + WSAGetLastError());std::cout << "创建套接字失败:"<< WSAGetLastError() << std::endl;WSACleanup();exit(0);}//填充服务端信息service_UDP_get.sin_family = AF_INET;  // 设置地址族为 IPv4service_UDP_get.sin_addr.s_addr = INADDR_ANY;  // 将 IP 地址设置为 0.0.0.0,表示绑定到所有本地 IP 地址service_UDP_get.sin_port = htons(port);   // 将端口号转换为网络字节序,并设置为指定的端口号// 绑定套接字if (bind(ListenSocket_UDP_get, (SOCKADDR*)&service_UDP_get, sizeof(service_UDP_get)) == SOCKET_ERROR){logger->error("绑定套接字失败: " + WSAGetLastError());std::cout << "绑定套接字失败: " + WSAGetLastError() << std::endl;closesocket(ListenSocket_UDP_get);WSACleanup();exit(0);}char recvbuf[512];  // 定义接收信息的缓冲区,大小为512字节int iRecvResult;  // 存储接收操作的返回结果sockaddr_in clientAddr;   // 用于存储客户端的地址信息int iAddrLen = sizeof(clientAddr);  // 存储地址结构体的大小do{	std::cout << "服务端正在等待数据发送,请稍候...." << std::endl;// 接收来自客户端的数据iRecvResult = recvfrom(ListenSocket_UDP_get, recvbuf, sizeof(recvbuf), 0, (SOCKADDR*)&clientAddr, &iAddrLen);// std::cout << iRecvResult << std::endl;// 检查接收操作是否成功if (iRecvResult > 0){std::string result(recvbuf, iRecvResult);std::cout << "收到信息:" + result << std::endl;logger->info("收到信息:" + result);// 将接收到的数据发送回客户端// sendto(ListenSocket_UDP, recvbuf, iRecvResult, 0, (SOCKADDR*)&clientAddr, sizeof(clientAddr));}else if (iRecvResult == 0){std::cout << "连接关闭" << std::endl;logger->info("连接关闭");}else{std::cout << "接受信息失败:" << WSAGetLastError() << std::endl;logger->error("接受信息失败:" + WSAGetLastError());closesocket(ListenSocket_UDP_get);WSACleanup();}} while (iRecvResult > 0);closesocket(ListenSocket_UDP_get);WSACleanup();
}void SocketManager::initialization() {//初始化套接字库WORD w_req = MAKEWORD(2, 2);//版本号WSADATA wsadata;int err;err = WSAStartup(w_req, &wsadata);if (err != 0) {std::cout << "初始化套接字库失败!" << std::endl;}//检测版本号if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {std::cout << "套接字库版本号不符!" << std::endl;WSACleanup();}//填充服务端地址信息
}void SocketManager::send_to_tcp(std::string str, std::string ip, int port) {int send_len = 0;// 初始化套接字库initialization();//填充服务端信息service_TCP_to.sin_family = AF_INET;service_TCP_to.sin_addr.S_un.S_addr = inet_addr(ip.c_str());service_TCP_to.sin_port = htons(port);//创建套接字SendSocket_TCP_to = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (SendSocket_TCP_to == INVALID_SOCKET) {logger->error("创建套接字失败:" + WSAGetLastError());std::cout << "创建套接字失败:" << WSAGetLastError() << std::endl;WSACleanup();exit(1);}if (connect(SendSocket_TCP_to, (SOCKADDR*)&service_TCP_to, sizeof(SOCKADDR)) == SOCKET_ERROR) {std::cout << "服务器连接失败:" << WSAGetLastError() << std::endl;logger->error("服务器连接失败:" + WSAGetLastError());WSACleanup();exit(1);}// 发送信息send_len = send(SendSocket_TCP_to, str.c_str(), str.size(), 0);if (send_len < 0) {std::cout << "发送失败:" << WSAGetLastError() << std::endl;logger->error("发送失败:" + WSAGetLastError());}std::cout << send_len << "发送成功" << std::endl;//关闭套接字//closesocket(SendSocket_TCP_to);//释放DLL资源//WSACleanup();
}void SocketManager::get_from_tcp(int port) {// 初始化套接字库initialization();// 创建套接字ListenSocket_TCP_get = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);   // tcp与udp之间有所不同if (ListenSocket_TCP_get == INVALID_SOCKET) {logger->error("创建套接字失败:" + WSAGetLastError());std::cout << "创建套接字失败:" << WSAGetLastError() << std::endl;WSACleanup();exit(1);}//填充服务端信息service_TCP_get.sin_family = AF_INET;  // 设置地址族为 IPv4service_TCP_get.sin_addr.s_addr = INADDR_ANY;  // 将 IP 地址设置为 0.0.0.0,表示绑定到所有本地 IP 地址service_TCP_get.sin_port = htons(port);   // 将端口号转换为网络字节序,并设置为指定的端口号// 绑定套接字if (bind(ListenSocket_TCP_get, (SOCKADDR*)&service_TCP_get, sizeof(service_TCP_get)) == SOCKET_ERROR){logger->error("绑定套接字失败: " + WSAGetLastError());std::cout << "绑定套接字失败: " + WSAGetLastError() << std::endl;closesocket(ListenSocket_TCP_get);WSACleanup();exit(1);}char recvbuf[512];  // 定义接收信息的缓冲区,大小为512字节int iRecvResult;  // 存储接收操作的返回结果int len = 0;//设置套接字为监听状态if (listen(ListenSocket_TCP_get, SOMAXCONN) < 0) {std::cout << "设置监听状态失败:" << WSAGetLastError() << std::endl;logger->error("设置监听状态失败:" + WSAGetLastError());WSACleanup();}std::cout << "服务端正在监听连接,请稍候...." << std::endl;len = sizeof(service_TCP_get);SOCKET ClientSocket = INVALID_SOCKET;  // 初始化 ClientSocket 变量并将其设置为无效的套接字do{std::cout << "服务端正在等待数据发送,请稍候...." << std::endl;ClientSocket = accept(ListenSocket_TCP_get, (SOCKADDR*)&service_TCP_get, &len); // 等待客户端连接请求并接受连接/*accept 函数会阻塞,直到有客户端连接请求到达,然后返回一个新的套接字ListenSocket_TCP_get 是服务器监听的套接字service_TCP_get 是用于存储客户端地址信息的结构体len 是地址结构体的大小,accept 函数调用时会被更新为实际的地址大小*/// std::cout << ClientSocket << std::endl;if (ClientSocket == SOCKET_ERROR) {std::cout << "算法端连接失败:" + WSAGetLastError() << std::endl;logger->error("算法端连接失败:" + WSAGetLastError());WSACleanup();exit(2);}// 接收来自客户端的数据iRecvResult = recv(ClientSocket, recvbuf, sizeof(recvbuf), 0);// 检查接收操作是否成功if (iRecvResult > 0){// std::cout << iRecvResult << std::endl;std::string result(recvbuf, iRecvResult);std::cout << "收到信息:" + result << std::endl;logger->info("收到信息:" + result);// 将接收到的数据发送回客户端// sendto(ListenSocket_UDP, recvbuf, iRecvResult, 0, (SOCKADDR*)&clientAddr, sizeof(clientAddr));}else if (iRecvResult == 0){std::cout << "连接关闭" << std::endl;logger->info("连接关闭");}else{std::cout << "接受信息失败:" << WSAGetLastError() << std::endl;logger->error("接受信息失败:" + WSAGetLastError());closesocket(ListenSocket_UDP_get);WSACleanup();}} while (iRecvResult > 0);closesocket(ListenSocket_TCP_get);WSACleanup();
}void SocketManager::send_to_udp(std::string str, std::string ip, int port) {int send_len = 0;// 初始化套接字库initialization();//填充服务端信息service_UDP_to.sin_family = AF_INET;service_UDP_to.sin_addr.S_un.S_addr = inet_addr(ip.c_str());service_UDP_to.sin_port = htons(port);//创建套接字SendSocket_UDP_to = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);if (SendSocket_UDP_to == INVALID_SOCKET) {logger->error("创建套接字失败:" + WSAGetLastError());std::cout << "创建套接字失败:" << WSAGetLastError() << std::endl;WSACleanup();exit(0);}int iSendResult = sendto(SendSocket_UDP_to, str.c_str(), str.size(), 0, (SOCKADDR*)&service_UDP_to, sizeof(service_UDP_to));if (iSendResult == SOCKET_ERROR) {std::cout << "发送失败:" << WSAGetLastError() << std::endl;logger->error("发送失败:" + WSAGetLastError());}//关闭套接字closesocket(SendSocket_UDP_to);//释放DLL资源WSACleanup();
}std::string asciiToHex(const std::string& asciiStr) {std::string hexStr;for (char c : asciiStr) {unsigned char value = static_cast<unsigned char>(c);hexStr += std::to_string(static_cast<int>(value >> 4)) + std::to_string(static_cast<int>(value & 0x0F));}return hexStr;
}

相关文章:

socket 收发TCP/UDP

一、c 个人测试记录&#xff0c;有问题还请指出&#xff0c;谢谢 参考&#xff1a;C开发基础之网络编程WinSock库使用详解TCP/UDP Socket开发_c udp使用什么库-CSDN博客 代码中Logger测试见文章&#xff1a; c中spdlog的使用/python中logger的使用-CSDN博客 1、main.cpp 收…...

Nest.js 实战 (三):使用 Swagger 优雅地生成 API 文档

什么是 Swagger ? Swagger 是一组围绕 OpenAPI 规范构建的开源工具&#xff0c;可以帮助您设计、构建、记录和使用 REST API。主要的 Swagger 工具 包括&#xff1a; Swagger Editor&#xff1a;基于浏览器的编辑器&#xff0c;您可以在其中编写 OpenAPI 定义Swagger UI&…...

spark shell

1.进行shell命令行 spark-shell 2.创建RDD 2.1 读取文件创建RDD 2.1.1读取linux文件系统的文件创建RDD --需要保证每一个worker中都有该文件 val data1 sc.textFile("file:/opt/file/word.txt") 2.1.2读取hdfs文件系统上的文件创建RDD val data2sc.textFile("…...

集群架构-web服务器(接入负载均衡+数据库+会话保持redis)--15454核心配置详解

紧接着前面的集群架构深化—中小型公司&#xff08;拓展到大型公司业务&#xff09;–下面图简单回顾一下之前做的及故障核心知识总结&#xff08;等后期完全整理后&#xff0c;上传资源希望能帮大家&#xff09; web集群架构-接入负载均衡部署web02服务器等 web集群-搭建web0…...

# Redis 入门到精通(七)-- redis 删除策略

Redis 入门到精通&#xff08;七&#xff09;-- redis 删除策略 一、redis 删除策略–过期数据的概念 1、Redis 中的数据特征 Redis 是一种内存级数据库&#xff0c;所有数据均存放在内存中&#xff0c;内存中的数据可以通过TTL指令获取其状态。 XX &#xff1a;具有时效性…...

10:00面试,10:08就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到6月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…...

html+canvas 实现签名功能-手机触摸

手机上的效果图 需要注意&#xff0c;手机触摸和鼠标不是一个事件&#xff0c;不能通用&#xff0c;上一篇是关于使用鼠标的样例 相关代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewpo…...

前端组件化探索与实践:Vue自定义暂无数据组件的开发与应用

摘要 随着前端开发技术的不断进步&#xff0c;组件化开发已成为提升开发效率、降低维护成本的关键手段。本文旨在通过介绍一款Vue自定义暂无数据组件的开发与实践&#xff0c;深入探讨前端组件化开发的重要性、优势及其在实际项目中的应用。 一、引言 在前端开发中&#xff0…...

《汇编语言 基于x86处理器》- 读书笔记 - Visual Studio 2019 配置 MASM环境

安装 Visual Studio 2019 配置 MASM环境 下载 Visual Studio Installer安装 Visual Studio 20191. 双击运行2. 自定义安装内容3. 修改 MSVC 工具集版本4. 设置主题&#xff08;可选&#xff09;5. 安装代码高亮插件 AsmDude&#xff08;可选&#xff09;6. 通义灵码&#xff08…...

Air780E/Air780EP/Air780EQ/Air201模块遇到死机问题如何分析

Air780E/Air780EP/Air780EQ/Air201模块遇到死机问题如何分析 简介 本文档适用于合宙Air780E、Air780EP、Air780EQ、Air201 关联文档和使用工具&#xff1a; 从Ramdump里分析内存泄漏问题 无法抓底层log的情况下如何导出死机dump Luatools下载调试工具 EPAT抓取底层日志 F…...

吴松洋院长 艺后整形集团专家组特约成员 全方位责任塑美

...

前端经验:使用sheetjs导出CSV文本为excel

应用场景 很多web表格组件没有提供直接的导出excel功能&#xff0c;但提供了导出CSV的功能。 如果能想办法拿到CSV的内容&#xff0c;就可以利用sheetjs生成excel并导出。 实施步骤 1.拿到CSV的内容字符 每种表格组件都有各自的CSV生成方法&#xff0c;不管用什么方法&…...

【nnUNetv2进阶】十五、nnUNetv2 魔改网络-小试牛刀-引入ECA

nnunet使用及改进教程。 【nnUNetv2实践】一、nnUNetv2安装 【nnUNetv2实践】二、nnUNetv2快速入门-训练验证推理集成一条龙教程 【nnUNetv2进阶】三、nnUNetv2 自定义网络-发paper必会-CSDN博客 其他网络改进参考: 【nnUNetv2进阶】四、nnUNetv2 魔改网络-小试牛刀-加入…...

centos(或openEuler系统)安装kafka集群

安装192.168.9.60、192.168.9.61、192.168.9.62这3台kafka集群&#xff08;kraft模式&#xff0c;不用zookeeper&#xff09; 不带密码的 1.每台机器安装kafka&#xff1a; cd /home/kafka wget https://downloads.apache.org/kafka/3.3.1/kafka_2.13-3.3.1.tgz 不通就换这…...

HarmonyOS根据官网写案列~ArkTs从简单地页面开始

Entry Component struct Index {State message: string 快速入门;build() {Column() {Text(this.message).fontSize(24).fontWeight(700).width(100%).textAlign(TextAlign.Start).padding({ left: 16 }).fontFamily(HarmonyHeiTi-Bold).lineHeight(33)Scroll() {Column() {Ba…...

GraphRAG+ollama+LM Studio+chainlit

这里我们进一步尝试将embedding模型也换为本地的&#xff0c;同时熟悉一下流程和学一些新的东西 1.环境还是用之前的&#xff0c;这里我们先下载LLM 然后你会在下载nomic模型的时候崩溃&#xff0c;因为无法搜索&#xff0c;无法下载 解决办法如下lm studio 0.2.24国内下载…...

【中项第三版】系统集成项目管理工程师 | 第 5 章 软件工程② | 5.4 - 5.8

前言 第 5 章对应的内容选择题和案例分析都会进行考查&#xff0c;这一章节属于技术的内容&#xff0c;学习要以教材为准。 目录 5.4 软件实现 5.4.1 软件配置管理 5.4.2 软件编码 5.4.3 软件测试 5.5 部署交付 5.5.1 软件部署 5.5.2 软件交付 5.5.3 持续交付 5.5.4…...

6. dolphinscheduler-3.0.0伪集群部署

环境说明&#xff1a; 主机名&#xff1a;cmc01为例 操作系统&#xff1a;centos7 安装部署软件版本部署方式centos7zookeeperzookeeper-3.4.10伪分布式hadoophadoop-3.1.3伪分布式hivehive-3.1.3-bin伪分布式clickhouse21.11.10.1-2单节点多实例dolphinscheduler3.0.0单节…...

防火墙内容安全综合实验

一、实验拓扑 二、实验要求 1&#xff0c;假设内网用户需要通过外网的web服务器和pop3邮件服务器下载文件和邮件&#xff0c;内网的FTP服务器也需要接受外网用户上传的文件。针对该场景进行防病毒的防护。 2&#xff0c;我们需要针对办公区用户进行上网行为管理&#xff0c;要…...

常见的数据分析用例 —— 信用卡交易欺诈检测

文章目录 引言数据集分析1. 读入数据并快速浏览2.计算欺诈交易占数据集中交易总数的百分比3. 类别不平衡对模型的影响3.1 总体思路&#xff08;1&#xff09;数据的划分&#xff08;2&#xff09;训练模型&#xff08;3&#xff09;测试模型&#xff08;4&#xff09;解决不平衡…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

WEB3全栈开发——面试专业技能点P4数据库

一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库&#xff0c;基于 mysql 库改进而来&#xff0c;具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点&#xff1a; 支持 Promise / async-await&#xf…...