TCP实现多线程远程命令执行
1.上一篇篇代码改进
bind的绑定第一个是对象,其余的都是参数,传给一个类需要this指针,所以有&r
错误地方是智能指针的参数要加&,thread.name()要删除
2.介绍需要用到函数
popen函数
FILE *popen(const char *command, const char *type);
-
command
:这是一个指向以空字符结尾的字符串的指针,该字符串包含要执行的命令。这个命令可以是任何可以在命令行中运行的命令。 -
type
:这是一个字符串,指定管道的方向。它只能是以下两种模式之一:-
"r"
:表示从子进程的输出中读取数据。 -
"w"
:表示向子进程的输入中写入数据。
-
2. 参数解释
-
cmd.c_str()
:cmd
是一个std::string
对象,cmd.c_str()
是一个成员函数,它返回一个指向以空字符结尾的字符串的指针。这个指针可以直接传递给popen
函数。 -
"r"
:表示从子进程的输出中读取数据。这意味着子进程的标准输出会被重定向到父进程的文件流中。
3. 返回值
-
popen
函数返回一个指向FILE
类型的指针,这个指针可以用于后续的 I/O 操作(如fread
、fwrite
、fgets
等)。 -
如果
popen
调用失败,返回值为NULL
。
listen函数
int listen(int sockfd, int backlog);
参数
-
sockfd
:已经绑定到本地地址的套接字描述符。 -
backlog
:未完成连接队列的最大长度。这个值表示操作系统可以为该套接字维护的未完成连接的最大数量。
返回值
-
成功时返回
0
。 -
失败时返回
-1
,并设置errno
以指示错误原因。
作用
-
将套接字从主动模式转换为被动模式,使其能够接收客户端的连接请求。
-
设置未完成连接队列的最大长度,当队列已满时,新的连接请求将被拒绝
connect函数
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数
-
sockfd
:客户端的套接字描述符。 -
addr
:指向struct sockaddr
的指针,包含服务器的地址信息。 -
addrlen
:addr
的长度。
返回值
-
成功时返回
0
。 -
失败时返回
-1
,并设置errno
以指示错误原因。
作用
-
将客户端的套接字连接到指定的服务器地址。
-
如果连接成功,套接字将进入已连接状态,可以进行数据传输。
accept函数
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数
-
sockfd
:监听套接字描述符。 -
addr
:指向struct sockaddr
的指针,用于存储客户端的地址信息。如果不需要获取客户端的地址信息,可以将其设置为NULL
。 -
addrlen
:指向socklen_t
的指针,表示addr
的长度。在调用accept
之前,需要将其设置为addr
的大小。调用后,addrlen
会被设置为实际存储在addr
中的地址的长度。
返回值
-
成功时返回一个新的套接字描述符,用于与客户端通信。
-
失败时返回
-1
,并设置errno
以指示错误原因。
作用
-
从监听队列中取出一个已完成的连接请求,并为该连接创建一个新的套接字。
-
新的套接字描述符可以用于与客户端进行数据传输。
fgets函数
char *fgets(char *str, int size, FILE *stream);
参数
-
str
:指向字符数组的指针,用于存储读取到的字符串。 -
size
:指定字符数组的最大长度。fgets
会读取最多size - 1
个字符,以确保在数组末尾添加空字符\0
。 -
stream
:文件流指针,指向要读取的文件。
返回值
-
如果成功读取到一行数据,返回值是
str
,即指向存储读取到的字符串的指针。 -
如果到达文件末尾或发生错误,返回值为
NULL
。
3.TcpServer文件
1.Init函数实现
开始在栈区上创建一个套接字,接着创建InetAddr类的对象,把端口号传过去,会构造一个sockaddr_in的结构体,并初始化这个结构体,接着把栈区上的套接字作为参数执行bind函数,进入到内核态中绑定,使套接字有效,因为是tcp通信就需要相互连接,就需要listen函数,把状态变为监听。
listen,connect和accept:
假设你正在经营一家餐厅,`listen`、`connect` 和 `accept` 的过程可以类比为以下场景:
1. **`listen`**:
- 你告诉员工:“开始接听预订电话。”
- 这时,你的电话系统(套接字)处于监听状态,准备接收客户的预订请求。2. **`connect`**:
- 客户拨打你的预订电话,尝试与你联系。
- 这就好比客户端调用 `connect`,向服务器发起连接请求。3. **`accept`**:
- 你的员工接听电话,并记录下客户的预订信息。
- 这就好比服务器调用 `accept`,接受客户端的连接请求,并为该客户分配一个新的资源
void Init(){_listensockfd=socket(AF_INET,SOCK_STREAM,0);if(_listensockfd<0){LOG(LogLevel::FATAL)<<"socket error";exit(SOCKET_ERR);}LOG(LogLevel::INFO)<<"socket success:"<<_listensockfd;InetAddr local(_port);int n=bind(_listensockfd,local.NetAddrPtr(),local.NetAddrLen());if(n<0){LOG(LogLevel::FATAL)<<"bind error";exit(BIND_ERR);}LOG(LogLevel::INFO)<<"bind success:"<<_listensockfd;n=listen(_listensockfd,backlog);if(n<0){LOG(LogLevel::FATAL)<<"listen error";exit(LISTEN_ERR);}LOG(LogLevel::INFO)<<"listen sucess:"<<_listensockfd;}InetAddr(uint16_t port):_port(port),_ip(){memset(&_addr,0,sizeof(_addr));_addr.sin_family=AF_INET;_addr.sin_addr.s_addr=INADDR_ANY;_addr.sin_port=htons(_port);}
2.service函数实现
创建一个缓冲区buffer,调用read函数读取文件描述符为sockfd的文件,把读取到的消息存储到buffer中,返回值n为实际读取到的大小,大于0就日志显示是谁发送的,然后执行回调函数_func,并把结果通过write函数写到文件描述符为sockfd的文件上,因为read函数会阻塞,所以需要设置多个判断,为0就说明没有输入,就i显示退出,然后关闭文件,取它的就是出现异常,关闭文件并退出。
void Service(int sockfd,InetAddr& peer){char buffer[1024];while(true){ssize_t n=read(sockfd,buffer,sizeof(buffer)-1);if(n>0){buffer[n]=0;LOG(LogLevel::DEBUG)<<peer.StringAddr()<<"#"<<buffer;std::string echo_string=_func(buffer,peer);write(sockfd,echo_string.c_str(),echo_string.size());}else if(n==0){LOG(LogLevel::DEBUG)<<peer.StringAddr()<<"退出了";close(sockfd);break;}else{LOG(LogLevel::DEBUG)<<peer.StringAddr()<<"异常";close(sockfd);break;}}}
3.Run函数实现
设置isrunning状态,创建sockaddr_in结构体,得到其大小,调用accept函数开始处理要连接的客服端,如果没有要连接的就会处于阻塞状态,连接成功就可以得到客服端的信息,放到类型为InetAddr的addr内部处理,可以打印出地址信息,接着就是处理任务了,这里方案是创建多线程,pthread_create函数创建线程,传入创建的tid,执行的函数Routine,以及this,执行函数内部是先设置为分离状态,避免阻塞(卡住主线程),创建ThreadData类原因是线程函数只能传一个参数,所以需要把所有的参数封装在一起,把结构体传过去,线程函数执行service函数,service函数内部有回调函数,所以就可以处理任务,拿到结果。
方案二:
通过fork函数创建子进程,id==0时是子进程执行的代码,然后关闭listensock,因为用不上避免错误,接着在创建一个子进程,也就是有爷子孙三个进程,把任务给孙子进程执行,然后关闭子进程,因为父进程要阻塞回收子进程资源,而关闭就不会了,孙子进程因为子进程关闭而变成孤儿进程,就会在任务执行完成后自动结束。
方案三:
线程池方案,使用lambda形式把任务入队列,提前设置线程最多数量,就可以把任务队列的任务取出来执行。
class ThreadData{public:ThreadData(int fd,InetAddr& ar,TcpServer* s):sockfd(fd),addr(ar),tsvr(s){}public:int sockfd;InetAddr addr;TcpServer* tsvr;};static void* Routine(void* args){pthread_detach(pthread_self());//避免阻塞ThreadData* td=static_cast<ThreadData*>(args);td->tsvr->Service(td->sockfd,td->addr);delete td;return nullptr;}void Run(){_isrunning=true;while(_isrunning){struct sockaddr_in peer;socklen_t len=sizeof(sockaddr_in);int sockfd=accept(_listensockfd,CONV(peer),&len);if(sockfd<0){LOG(LogLevel::WARNING)<<"accept error";continue;}InetAddr addr(peer);LOG(LogLevel::INFO)<<"accept success ,peer addr:"<<addr.StringAddr();//多线程版本ThreadData* td=new ThreadData(sockfd,addr,this);pthread_t tid;pthread_create(&tid,nullptr,Routine,td);// //父进程// pid_t id=fork();// if(id<0)// {// LOG(LogLevel::FATAL)<<"fork error";// exit(FORK_ERR);// }// else if(id==0)// {// //不让子进程访问listensock// close(_listensockfd);// if(fork()>0)// exit(OK);// Service(sockfd,addr);// exit(OK);// }// else// {// close(sockfd);// pid_t rid=waitpid(id,nullptr,0);// (void)rid;// }// //线程池版本,适合于短服务// ThreadPool<task_t>::GetInstance()->Enqueue([this,sockfd,&addr](){// this->Service(sockfd,addr);// });}_isrunning=false;}
4.Server.cc文件
Usage函数目的是命令行参数不足时执行这个函数,主函数获取命令行参数,得到端口号,创建command对象,然后智能指针指向用make_unique创建的对象,这个对象的创建就可以看知道回调函数就是执行execute,参数为端口号和bind绑定的Command内部的函数,也可以不绑定,就是一个端口号和要执行什么任务作为参数,调用创建对象的init函数和run函数。
#include "Command.hpp"
#include "TcpServer.hpp"std::string defaulthandler(const std::string& word,InetAddr& addr)
{LOG(LogLevel::DEBUG)<<"回调到了defaulthander";std::string s="haha ";s+=word;return s;
}void Usage(std::string proc)
{std::cerr<<"Usage:"<<proc<<"port"<<std::endl;
}int main(int argc,char* argv[])
{if(argc!=2){Usage(argv[0]);exit(USAGE_ERR);}uint16_t port=std::stoi(argv[1]);Enable_Console_Log_Strategy();Command cmd;std::unique_ptr<TcpServer> tsvr=std::make_unique<TcpServer>(port,std::bind(&Command::Execute,&cmd,std::placeholders::_1,std::placeholders::_2));tsvr->Init();tsvr->Run();
}
5. Tcpclient.cc文件
读取命令行参数,获得端口号和ip地址,创建套接字,客服端的套接字不需要绑定,避免端口冲突,os会自动随机绑定空的端口,创建类型为InetAddr的serveraddr对象,会对地址和端口号进行处理,执行connect函数,发起连接请求,服务器执行accept函数就会完成连接。while一直循环,创建line读取cin输入流内容,输入流会完line里面写入,执行write函数把line内容写到文件描述符为sockfd的文件,创建buffer,调用read函数把sockfd对应的文件内容读到buffer里面,读取成功打印buffer内容,最后关闭文件。
#include <iostream>
#include "Common.hpp"
#include "InetAddr.hpp"void Usage(std::string proc)
{std::cerr<<"Usage::"<<proc<<"server_ip server_port"<<std::endl;
}int main(int argc,char* argv[])
{if(argc!=3){Usage(argv[0]);exit(USAGE_ERR);}std::string serverip=argv[1];uint16_t serverport=std::stoi(argv[2]);int sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd<0){std::cerr<<"sock error"<<std::endl;exit(SOCKET_ERR);}InetAddr serveraddr(serverip,serverport);int n=connect(sockfd,serveraddr.NetAddrPtr(),serveraddr.NetAddrLen());if(n<0){std::cerr<<"connect error"<<std::endl;exit(CONNECT_ERR);}while(true){std::string line;std::cout<<"Please Enter@";getline(std::cin,line);write(sockfd,line.c_str(),line.size());char buffer[1024];ssize_t size=read(sockfd,buffer,sizeof(buffer)-1);if(size>0){buffer[size]=0;std::cout<<"server echo#"<<buffer<<std::endl;}}close(sockfd);return 0;
}
6.Common.hpp文件
实现了一个枚举,跟exit搭配,对应不同退出信息,NoCopy类是不可以靠谱构造和赋值重载的,于继承一起,就可以让禁止拷贝和赋值的类继承这个类,就可以不用在内部写多份(多个类都要满足禁止拷贝和赋值),只要作为NoCopy类的派生类就不可以拷贝和赋值。
#pragma once#include <iostream>
#include <functional>
#include <unistd.h>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>enum ExitCode
{OK=0,USAGE_ERR,SOCKET_ERR,BIND_ERR,LISTEN_ERR,CONNECT_ERR,FORK_ERR
};class NoCopy
{
public:NoCopy() {}~NoCopy() {}NoCopy(const NoCopy&) =delete;const NoCopy& operator=(const NoCopy&) =delete;
};#define CONV(addr) ((struct sockaddr*)&addr)
7.Command.hpp文件
远端执行远程命令,就需要设置一些限制,不然执行一些命令,比如删除,创建这类执行是危险的,成员变量为set的容器,把可以用的命令放到容器中,只用输入这些指令才是有效的,其余都是无用的,issafecommand函数可以判断,通过遍历容器。execute函数是具体的处理,先判断指令是否在容器中,接着执行popen函数,用于子进程来执行指定的命令,并通过管道于子进程的输出进行交互,使用fgets函数从fp指向的文件进行读取内容,按行读取直到没有为止,然后把读取的内容与格式话拼接,把结果返回,然后server端就可以得到最后返回的结果。
#pragma once#include <iostream>
#include <string>
#include <cstdio>
#include <set>
#include "Command.hpp"
#include "InetAddr.hpp"
#include "Log.hpp"using namespace LogModule;class Command
{
public:Command(){_WhiteListCommands.insert("ls");_WhiteListCommands.insert("pwd");_WhiteListCommands.insert("ls -l");_WhiteListCommands.insert("touch haha.txt");_WhiteListCommands.insert("who");_WhiteListCommands.insert("whoami");}bool IsSafeCommand(const std::string& cmd){auto iter=_WhiteListCommands.find(cmd);return iter!=_WhiteListCommands.end();}std::string Execute(const std::string& cmd,InetAddr& addr){if(!IsSafeCommand(cmd)){return std::string("违规");}std::string who=addr.StringAddr();FILE* fp=popen(cmd.c_str(),"r");if(nullptr==fp){return std::string("执行命令不存在:")+cmd;}std::string res;char line[1024];while(fgets(line,sizeof(line),fp)){res+=line;}pclose(fp);std::string result=who+"execute done,result is: \n"+res;LOG(LogLevel::DEBUG)<<result;return result;}~Command(){}
private:std::set<std::string> _WhiteListCommands;
};
相关文章:
TCP实现多线程远程命令执行
1.上一篇篇代码改进 bind的绑定第一个是对象,其余的都是参数,传给一个类需要this指针,所以有&r 错误地方是智能指针的参数要加&,thread.name()要删除 2.介绍需要用到函数 popen函数 FILE *popen(const char *command, …...
【MySQL】索引特性
文章目录 👉没有索引可能会有什么问题👈👉认识磁盘👈前置知识MySQL 与磁盘磁盘定位扇区结论磁盘随机访问与连续访问MySQL 与磁盘交互基本单位 👉MySQL 的整体轮廓👈👉索引的理解👈建…...
红宝书第四十七讲:Node.js服务器框架解析:Express vs Koa 完全指南
红宝书第四十七讲:Node.js服务器框架解析:Express vs Koa 完全指南 资料取自《JavaScript高级程序设计(第5版)》。 查看总目录:红宝书学习大纲 一、框架定位:HTTP服务器的工具箱 共同功能: 快…...
SDK游戏盾ip可以破解吗
从技术实现和法律合规性角度,不建议也不应尝试破解SDK游戏盾的IP防护机制。以下是详细分析: 一、法律与道德风险 违法行为 破解游戏盾的IP防护属于非法侵入计算机信息系统或破坏网络安全的行为,可能…...
eBay东南亚爆单密码:72小时交付计划如何重构厦门仓+东南亚供应链?
2024年东南亚电商市场规模预计突破2340亿美元,年复合增长率达18%。eBay最新战略将厦门纳入海外仓核心节点,推出“72小时交付计划”,通过“仓配转”一体化链路,助力中国卖家实现东南亚市场订单履约率提升10%,退货成本降…...
大语言模型
1.当前有哪些主流AI方向 1.1大语言模型方向 OpenAI的GPT语言模型系列,o3等推理模型系列 综合能力强 anthrotic的claude系列,推理预测混合模型 代码能力强 DeepSeek的V系列,R1推理模型 …...
深入理解Java缓冲输入输出流:性能优化的核心武器
在Java应用程序的IO操作中,频繁的磁盘读写或网络传输往往是性能瓶颈的主要来源。JDK提供的缓冲流(Buffered Streams)通过内存缓冲机制,将零碎的IO操作转化为批量处理,成为提升IO效率的关键技术。本文将从设计原理、核心机制到实战技巧,全面解析缓冲流的技术细节。 一、缓…...
AI 对话高效输入指令攻略(一):了解AI对话指令
目录 引 一.认识 AI 对话中的指令基础 1.运行原理 2.智能体在 AI 对话中的关键角色与运行机制 3.智能体的核心任务 4.对不同指令的响应差异 5.针对不同指令类型的处理方式 6.智能体在底层逻辑中的运作 二.高效输入指令的底层逻辑 1.语义匹配逻辑 …...
AI大模型从0到1记录学习 数据结构和算法 day19
常用算法 查找算法 二分查找 算法原理 二分查找又称折半查找,适用于有序列表。其利用数据的有序性,每轮缩小一半搜索范围,直至找到目标元素或搜索区间为空为止。 代码实现 def binary_search(arr, target): left, right 0, len(arr) - 1 w…...
Python + Playwright:使用正则表达式增强自动化测试
Python + Playwright:使用正则表达式增强自动化测试 前言一、 为什么选择正则表达式?二、 Playwright 中集成正则表达式:途径与方法三、 实战应用:正则表达式解决典型测试难题场景 1:定位 ID 或 Class 包含动态部分的元素场景 2:验证包含可变数字或文本的提示信息场景 3:…...
构建用户友好的记账体验 - LedgerX交互设计与性能优化实践
构建用户友好的记账体验 - LedgerX交互设计与性能优化实践 发布日期: 2025-04-16 引言 在财务管理应用领域,技术实力固然重要,但最终决定用户留存的往往是日常使用体验。本文作为LedgerX技术博客的第二篇,将深入探讨我们如何通过精心的交互…...
AI赋能PLC(一):三菱FX-3U编程实战初级篇
前言 在工业自动化领域,三菱PLC以其高可靠性、灵活性和广泛的应用场景,成为众多工程师的首选控制设备。然而,传统的PLC编程往往需要深厚的专业知识和经验积累,开发周期长且调试复杂。随着人工智能技术的快速发展,利用…...
人工智能——梯度提升决策树算法
目录 摘要 14 梯度提升决策树 14.1 本章工作任务 14.2 本章技能目标 14.3 本章简介 14.4 编程实战 14.5 本章总结 14.6 本章作业 本章已完结! 摘要 本章实现的工作是:首先采用Python语言读取含有英语成绩、数学成绩以及学生所属类型的样本数据…...
智能家居适老化改造:让科技回归“无感服务”
在老龄化加速与科技飞速发展的当下,智能家居适老化改造成为提升老年人生活品质的关键举措。 理想的适老化智能家居,应实现 “无感服务”,即让老年人在无需刻意操作或复杂学习的情况下,自然、流畅地享受科技带来的便利,…...
2025年最新Web安全(面试题)
活动发起人小虚竹 想对你说: 这是一个以写作博客为目的的创作活动,旨在鼓励大学生博主们挖掘自己的创作潜能,展现自己的写作才华。如果你是一位热爱写作的、想要展现自己创作才华的小伙伴,那么,快来参加吧!…...
【linux】命令收集
1. 系统信息 uname -m:显示处理器架构uname -r:显示内核版本arch:显示处理器架构cat /proc/cpuinfo:查看CPU信息cat /proc/meminfo:查看内存使用情况cat /proc/version:显示内核版本date:显示系…...
从零到一:网站设计新手如何快速上手?
从零到一:网站设计新手如何快速上手? 在当今数字化时代,网站已成为企业、个人展示信息、提供服务的重要窗口。对于想要涉足网站设计领域的新手而言,如何快速上手并掌握必要的技能成为首要任务。本文将从基础知识、软件工具、设计…...
API平台(API网关)的API安全保障机制
API安全保障机制是一个复杂而重要的任务,需要综合运用多种技术和策略来确保API的安全性和稳定性。 1.黑名单 将不合法的服务、API及终端加入平台黑名单,限制其访问。支持黑名单的列表展示,且可将内容从黑名单删除。按类型、内容搜索黑名单。…...
【软考】论devops在企业信息系统开发中的应用
摘要: 随着互联网的不断发展,各行各业都在建设自己的企业信息系统,而随着业务的不断升级和复杂化,系统的更新迭代速度越来越快,系统也越来越复杂。对于信息系统开发者,架构师,管理者,…...
端、管、云一体化原生安全架构 告别外挂式防护!
面对数字化转型浪潮,企业网络安全风险日益凸显。数据泄露、黑客勒索等事件频发,合规要求加速推进。尽管企业纷纷部署了防病毒、身份认证、文件加密、入侵防护、流量监控等多种安全系统,但分散且孤立的架构非但没有有效抵御风险,反…...
每天记录一道Java面试题---day39
GC如何判断对象可以被回收了 回答重点 引用计数法: - 每个对象由一个引用计数属性,新增一个引用时计数器加1,引用释放时计数减1,计数为0时可以回收。可达性分析法: - 从GC Roots开始向下搜索,搜索所走过的…...
码界奇缘 Java 觉醒 后记 第二十五章 安全结界攻防战 - 从沙箱到模块化
第二十五章:安全结界攻防战 - 从沙箱到模块化 知识具象化场景 陆小柒站在由安全策略文件堆砌的古城墙上,眼前是千疮百孔的沙箱结界。空中漂浮着残缺的SecurityManager符石,远处java.security包化身的青铜守卫正在崩塌: 权限校验…...
【数据结构】励志大厂版·初阶(复习+刷题):线性表(顺序表)
前引:上一篇我们复习了复杂度,今天我们来通过实践回忆我们的线性表知识点,下面将讲解什么是线性表,顺序结构又是什么,知识点简洁精髓,无废话可言,小编会从每个细节讲起,包含头文件的…...
C 语言结构体中的函数指针与 Kotlin 高阶函数的对比
在学习 C 语言的过程中,很多 Java/Kotlin 背景的开发者都会对结构体中出现的“函数指针”感到陌生。特别是当看到如下代码时: struct Animal {void (*speak)(void); };void dogSpeak() {printf("Woof!\n"); }int main() {struct Animal dog;d…...
MicroK8s和K8s的区别优劣在哪?
运行ubuntu24.04后提示这么一段话: Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8sjust raised the bar for easy, resilient and secure K8s cluster deployment.https://ubuntu.com/engage/secure-kubernetes-at-the-edge 这段话…...
C++指针和引用之区别(The Difference between C++Pointers and References)
面试题:C指针和引用有什么区 C指针和引用有什么区别? 在 C 中,指针和引用都是用来访问其他变量的值的方式,但它们之间存在一些重要的区别。了解这些区别有助于更好地理解和使用这两种工具。 01 指针 指针(Pointer…...
Linux——Shell编程之正则表达式与文本处理器(笔记)
目录 基础正则表达式 1:基础正则表达式示例 (4)查找任意一个字符“.”与重新字符“*” (5)查找连续字符范围“{ }” 文本处理器 一、sed工具 二、awk工具 (1)按行输出文本 (2࿰…...
关于k8s的部署
一、实验目的 1、理解k8s的组件的功能; 2、理解k8s中的资源类型; 3、 熟练掌握k8s部署配置; 二、实验内容: 前置知识点: 写出k8s有哪些组件并简述作用? ①Master 组件: Master 组件提供集…...
营销自动化实战指南:如何用全渠道工作流引爆线索转化率?
在数字化浪潮席卷全球的今天,企业争夺用户注意力的战场已从单一渠道转向全渠道。然而,面对海量线索,许多团队依然深陷效率泥潭:人工处理耗时费力、高价值线索流失、跨渠道数据难以整合……如何破局?营销自动化正成为企…...
利用Global.asax在ASP.NET Web应用中实现功能
Global.asax文件(也称为ASP.NET应用程序文件)是ASP.NET Web应用程序中的一个重要文件,它允许您处理应用程序级别和会话级别的事件。下面介绍如何利用Global.asax来实现各种功能。 Global.asax基本结构 <% Application Language"C#&…...
【Linux 并发与竞争实验】
【Linux 并发与竞争实验】 之前学习了四种常用的处理并发和竞争的机制:原子操作、自旋锁、信号量和互斥体。本章我们就通过四个实验来学习如何在驱动中使用这四种机制。 文章目录 【Linux 并发与竞争实验】1.原子操作实验1.1 实验程序编写1.2 运行测试 2.自旋锁实验…...
数据一致性策略之延迟双删-实现
延迟双删 查询数据之前优先去查Redis的缓存数据,减少数据库压力; 如果没有缓存会去查数据库,通过查询数据库后缓存热点Key Cache-Aside策略 高并发场景时,严重生产bug:数据不一致 业务场景: 事务1&#x…...
在PyTorch中,使用不同模型的参数进行模型预热
在PyTorch中,使用不同模型的参数进行模型预热(Warmstarting)是一种常见的迁移学习和加速训练的策略。以下是结合多个参考资料总结的实现方法和注意事项: 1. 核心机制:load_state_dict()与strict参数 • 部分参数加载&…...
【AI论文】InternVL3:探索开源多模态模型的高级训练和测试时间配方
摘要:我们推出了InternVL3,这是InternVL系列的一项重大进步,具有本地多模态预训练范式。 InternVL3不是将纯文本的大型语言模型(LLM)改编成支持视觉输入的多模态大型语言模型(MLLM),…...
基于Linux的ffmpeg python的关键帧抽取
1.FFmpeg的环境配置 首先强调,ffmpeg-python包与ffmpeg包不一样。 1) 创建一个虚拟环境env conda create -n yourenv python3.x conda activate yourenv2) ffmpeg-python包的安装 pip install ffmpeg-python3) 安装系统级别的 FFmpeg 工具 虽然安装了 ffmpeg-p…...
CNN:卷积到底做了什么?
卷积神经网络(Convolutional Neural Network, CNN) 是一种深度学习模型,专门用于处理具有网格结构的数据(如图像、视频等)。它在计算机视觉领域表现卓越,广泛应用于图像分类、目标检测、图像分割等任务。CN…...
C++ IO流
文章目录 C IO流流是什么C标准IO流C文件IO流c字符串流 C IO流 流是什么 在 C 中,“流(Stream)” 是一种 抽象的数据传输机制,它通过统一的接口实现了程序与各种输入/输出设备(如键盘、屏幕、文件、内存等)…...
解决splice改变原数组的BUG(拷贝数据)
项目场景: 项目中难免遇到需要删除改变数组的方法,去重,删除不要的数据等 问题描述: 但是splice方法会删除掉数据改变原数组,返回的是改变之后的数组,即使你是赋值的还是会影响到原数组的数据 GoodsInfo…...
ARINC818协议(二)
ARINC818对图像数据进行帧分割 1.FC协议定了5层模型结构:FC-4;FC-3;FC-2;FC-1;FC-0; 2.ARINC818协议位于FC-4层; 3.ARINC818协议在FC-4层使用FHCP帧头控制协议进行实现数据传递; 4.协议中有容器,容器头,object0~object…...
【Netty篇】Future Promise 详解
目录 一、 Netty Future 与 Promise —— 异步世界的“信使”与“传话筒”🚀1、 理解 Netty Future2、 理解 Netty Promise 二、 代码案例解读💻例1:同步处理任务成功👍例2:异步处理任务成功📲例3ÿ…...
【LaTeX】Misplaced alignment tab character . ^^I
目录 公式中出现Misplaced alignment tab character &. ^^I& 解决1:采用&& 解决2: 公式中出现Misplaced alignment tab character &. ^^I& \begin{equation}J_r & \dfrac{i\hbar}{2m}\left[\psi_2 \dfrac{\partial \psi^…...
数据中台(大数据平台)之元数据管理
👉元数据管理是数据管理的基础,数据中台产品要能够提供各类元数据采集的适配器,自动化采集技术元数据,并在技术元数据的基础上补充管理属性和业务属性,为后续的数据资源目录、数据安全管控、报表开发提供统一的口径。并…...
基于RRT的优化器:一种基于快速探索随机树算法的新型元启发式算法
受机器人路径规划中常用的快速探索随机树(RRT)算法的搜索机制的启发,我们提出了一种新颖的元启发式算法,称为基于RRT的优化器(RRTO)。这是首次将RRT算法的概念与元启发式算法相结合。RRTO的关键创新是其三种…...
设计模式每日硬核训练 Day 13:桥接模式(Bridge Pattern)完整讲解与实战应用
🔄 回顾 Day 12:装饰器模式小结 在 Day 12 中,我们学习了装饰器模式(Decorator Pattern): 强调在不改变原类结构的前提下,动态为对象增强功能。通过“包装对象”实现运行时组合,支…...
【开发语言】悬空指针问题
悬空指针(Dangling Pointer)是编程中常见的内存管理问题,尤其在C/C这类手动管理内存的语言中。以下是详细解释: 什么是悬空指针? 悬空指针是指向已经被释放(或失效)内存的指针。这段内存可能已…...
深入剖析 WiFi 定位解析功能:原理、技术优势与应用场景
WiFi 定位解析功能的原理 信号强度与距离的关系 WiFi 定位的核心原理基于无线信号传播过程中的一个基本特性:信号强度与信号发射源(即 WiFi 接入点,Access Point,简称 AP)和接收设备之间距离的关联。一般来说&am…...
从标准九九表打印解读单行表达式的书写修炼(Python)
解读单行表达式书写,了解修习单行捷径。 笔记模板由python脚本于2025-04-16 23:24:17创建,本篇笔记适合喜欢单行喜好python的coder翻阅。 【学习的细节是欢悦的历程】 博客的核心价值:在于输出思考与经验,而不仅仅是知识的简单复述…...
HTML5好看的水果蔬菜在线商城网站源码系列模板4
文章目录 1.设计来源1.1 主界面1.2 关于我们1.3 商品信息1.4 新闻资讯1.5 联系我们1.5 登录注册 2.效果和源码2.1 动态效果2.2 源代码 源码下载 作者:xcLeigh 文章地址:https://blog.csdn.net/weixin_43151418/article/details/147264262 HTML5好看的水果…...
Arkts应用全局UI状态存储和持久化V2(AppStorageV2、PersistenceV2和@Type)
目录 应用全局UI状态存储和持久化V2版本 AppStorageV2 connect remove keys 示例 使用限制 PersistenceV2 connect remove keys save notifyOnError 示例 使用限制 Type 使用限制 应用全局UI状态存储和持久化V2版本 以下实例AppStorageV2、PersistenceV2和装饰…...
【QT】常用控件 【多元素类 | 容器类 | 布局类】
🌈 个人主页:Zfox_ 🔥 系列专栏:Qt 目录 一:🔥 QT 常用控件【多元素类】 🦋 List Widget -- 列表🦋 Table Widget -- 表格🦋 Tree Widget -- 树形 二:&#x…...