Linux实现翻译以及群通信功能
1.翻译功能实现
UdpServer.hpp文件
构造函数
接收一个端口号和一个回调函数,回调函数是传入一个执行方法,比如翻译方法。
UdpServer(uint16_t port,func_t func):_sockfd(defaultfd),_port(port),_isrunning(false),_func(func){}
Init函数
首先创建了一个端口号,然后使用setsockopt函数对端口进行控制,在定义了一个sockaddr_in结构体来作为参数,为发送做准备,需要把sockaddr_in进行初始化变成有效的参数,sin_family是协议,sin_port是端口,sin_addr.s_addr是地址,INADDR_ANY为地址来接收所有发送的信息,bind函数是这个在栈区上的端口变得有效,需要到内核态处理。
void Init(){_sockfd=socket(AF_INET,SOCK_DGRAM,0);if(_sockfd<0){LOG(LogLevel::FATAL)<<"socket error";exit(1);}int opt = 1;setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));LOG(LogLevel::INFO)<<"socket success, sockfd:"<<_sockfd;struct sockaddr_in local;bzero(&local,sizeof(local));local.sin_family=AF_INET;local.sin_port=htons(_port);local.sin_addr.s_addr=INADDR_ANY;int n=bind(_sockfd,(struct sockaddr*)&local,sizeof(local));if(n<0){LOG(LogLevel::FATAL)<<"bind error";exit(2);}LOG(LogLevel::INFO)<<"bind success,sockfd:"<<_sockfd;}
start函数
设置running状态为运行状态,创建一个buffer来接收消息,设置一个sockaddr_in结构体作为输出型参数,因为发送消息,是需要包含发送方的属性信息,所以要把结构体进行初始化为0,还需要传入这个结构体长度,就可以发送消息出去了,s是recvfrom函数的返回值,表示实际发送的字节个数,接收成功s一定会大于0,进入if里面执行,里面定义了一个client对象,类型是InetAddr类型的,用来处理端口号以及地址的序列形式,然后调用回调函数,传入接收消息的buffer和client对象,回调函数是在UdpServer.cc文件里传入的,回调函数是一个lambda形式,会调用Translate这个函数进行翻译工作。
void Start(){_isrunning=true;while(_isrunning){char buffer[1024];struct sockaddr_in peer;socklen_t len=sizeof(peer);memset(&peer,0,len);std::cout<<"recvfrom"<<std::endl; ssize_t s=recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);std::cout<<"recvfrom ok:" << s <<std::endl; std::cout<<s<<std::endl;if(s>0){InetAddr client(peer);buffer[s]=0;std::string result=_func(buffer,client);std::cout<<"send success"<<std::endl; std::cout<<"结果:"<<result<<std::endl;sendto(_sockfd,result.c_str(),result.size(),0,(struct sockaddr*)&peer,len);}}}std::unique_ptr<UdpServer> usvr=std::make_unique<UdpServer>(port, [&dict](const std::string& word,InetAddr& cli)->std::string {return dict.Translate(word,cli);
UdpServer.cc文件
通过命令行参数来获取端口号,设置日志模式输出到控制台,创建Dict类型对象,并执行这个对象的方法,然后是智能指针管理一个UdpServer类型的对象,传入参数端口号和回调函数的实现方法,启动Init函数和Start函数。
#include <iostream>
#include <memory>
#include "UdpServer.hpp"
#include <functional>
#include "Dict.hpp"
std::string defaulthandler(const std::string& message)
{std::cout<<"打印"<<std::endl;std::string hello="hello, ";hello+=message;return hello;
}int main(int argc,char* argv[])
{if(argc!=2){std::cerr<<"Usage:"<<argv[0]<<" port"<<std::endl;return 1;}uint16_t port=std::stoi(argv[1]);Enable_Console_Log_Strategy();Dict dict;dict.LoadDict();std::unique_ptr<UdpServer> usvr=std::make_unique<UdpServer>(port, [&dict](const std::string& word,InetAddr& cli)->std::string {return dict.Translate(word,cli);});usvr->Init();usvr->Start();return 0;
}
Dict.hpp文件
构造函数
把给定的文件路径赋值给成员变量,path就是一个完整的路径和文件名字,sep是分隔符,分开中英文。
#pragma once#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include "Log.hpp"
#include "InetAddr.hpp"const std::string defaultdict="./dictionary.txt";
const std::string sep=": ";Dict(const std::string& path=defaultdict):_dict_path(path){}private:std::string _dict_path;//路径+文件名std::unordered_map<std::string,std::string> _dict;
LoadDict函数
创建ifstream类型的对象in就会自动尝试打开所提供路径的文件,这个是通过ifstream的构造函数实现的,接着创建一个string类型的line,调用getline函数,参数是in和line,就会把输入流in中读取内容到string类型的line中存储,然后遇到换行符(\n)就会停下。读取成功进入循环体函数,pos迭代器指向sep符号,如果没有找到这个符号就打印解析失败,创建两个string类型的对象,调用string的substr函数进行部分拷贝,0到pos就是英文单词部分,二pos+sep的大小就是中文位置,其中之一读取为空就说明缺失内容,然后把读取的英文和中文放到哈希表里,就可以通过英文找到中文意思,最后关闭打开的输入流。
}
const std::string defaultdict="./dictionary.txt";
const std::string sep=": ";bool LoadDict(){std::ifstream in(_dict_path);if(!in.is_open()){LOG(LogLevel::DEBUG)<<"打开字典"<<_dict_path<<"错误";return false;}std::string line;while(std::getline(in,line)){auto pos=line.find(sep);if(pos==std::string::npos){LOG(LogLevel::WARNING)<<"解析"<<line<<"失败";continue;}std::string english=line.substr(0,pos);std::string chinese=line.substr(pos+sep.size());if(english.empty()||chinese.empty()){LOG(LogLevel::WARNING)<<"没有有效内容:"<<line;continue;}_dict.insert(std::make_pair(english,chinese));LOG(LogLevel::DEBUG)<<"加载"<<line;}in.close();return true;}
Translate函数
参数给了一个英文单词,调用find函数就找到这个单词的位置,不等于end的位置就说明找到了,用传入的client对象可以获取端口号和地址进行日志输出,返回iter的second,就会pair的第二个对象的值,也就是中文。
std::string Translate(const std::string& word,InetAddr& client){auto iter=_dict.find(word);if(iter==_dict.end()){LOG(LogLevel::DEBUG)<<"进入到翻译模块,["<<client.Ip()<<" : "<<client.Port()<<"]#"<<word<<"->Mone";return "None";}LOG(LogLevel::DEBUG)<<"进入到翻译模块,["<<client.Ip()<<" : "<<client.Port()<<"]#"<<word<<"->"<<iter->second;return iter->second;}
UdpClient.cc文件
命令行参数读取端口号和地址,创建端口并设置为udp模式,创建sockaddr_in结构体,并初始化创建的结构体,然后不用绑定端口号,避免端口冲突,会默认随机绑定一个空的端口号,使用getline函数从cin输入流中读取内容并存储到input中,使用sendto函数发送消息,除了套接字,发送内容以及大小,发送行为的设置,还要传入一个指针,指定数据的接收地方的地址,目标地址的长度。
可以从命令行参数得到接收方的地址在那里,在创建一个buffer来接收消息,创建一个sockaddr_in类型的结构体,初始化结构体,指向函数recvfrom函数进行接收,接收成功就打印buffer内容。
昨天代码的客户端没有使用bind函数,是为了避免端口冲突,服务端就像110,客户端就像人,只要电话号码是唯一就行,是什么没有关系,110是不能随便改的。
#include <iostream>
#include <string>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>int main(int argc,char* argv[])
{if(argc!=3){std::cerr<<"Usage:"<<argv[0]<<"server_ip server_port"<<std::endl;return 1;}std::string server_ip=argv[1];uint16_t server_port=std::stoi(argv[2]);int sockfd=socket(AF_INET,SOCK_DGRAM,0);if(sockfd<0){std::cerr<<"socket error"<<std::endl;return 2;}struct sockaddr_in server;memset(&server,0,sizeof(server));server.sin_family=AF_INET;server.sin_port=htons(server_port);server.sin_addr.s_addr=inet_addr(server_ip.c_str());while(true){std::string input;std::cout<<"Please Enter#";std::getline(std::cin,input);std::cout << "客户端发送数据: " << input.c_str() << std::endl;ssize_t n=sendto(sockfd,input.c_str(),input.size(),0,(struct sockaddr*)&server,sizeof(server));(void)n;std::cout<<"n:" << n<<std::endl;char buffer[1024];struct sockaddr_in peer;socklen_t len=sizeof(peer);ssize_t m=recvfrom(sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);if(m>0){buffer[m]=0;std::cout<<"进入判断"<<std::endl;std::cout<<"buffer:"<<buffer<<std::endl;std::cout<<buffer<<std::endl;}}return 0;
}
InnetAddr.hpp文件
把处理端口号和地址序列转换进行封装。
#pragma once
#include <iostream>
#include <string>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>//用于将网络地址和主机地址之间进行类型转换class InetAddr
{
public:InetAddr(struct sockaddr_in &addr):_addr(addr){_port=ntohs(_addr.sin_port);_ip=inet_ntoa(_addr.sin_addr);}uint16_t Port() {return _port;}std::string Ip() {return _ip;}~InetAddr(){}
private:struct sockaddr_in _addr;std::string _ip;uint16_t _port;
};
字典文件内容
apple: 苹果
banana: 香蕉
cat: 猫
dog: 狗
book: 书
pen: 笔
happy: 快乐的
sad: 悲伤的
hello:
: 你好
run: 跑
jump: 跳
teacher: 老师
student: 学生
car: 汽车
bus: 公交车
love: 爱
hate: 恨
hello: 你好
goodbye: 再见
summer: 夏天
winter: 冬天
2.多人通信实现
代码存在缺陷,下一篇文章改正,仅提供思路
全部代码文件链接:http://lesson39/3.ChatServer
UdpServer.hpp文件
Start函数
这里则不进行执行任务了,而是执行回调函数来实现任务,把套接字和信息以及接收方端口信息作为参数传过去
void Start(){_isrunning = true;while (_isrunning){char buffer[1024];struct sockaddr_in peer;socklen_t len = sizeof(peer);// 1. 收消息, client为什么要个服务器发送消息啊?不就是让服务端处理数据。ssize_t s = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &len);if (s > 0){InetAddr client(peer);buffer[s] = 0;// TODO_func(_sockfd, buffer, client);// LOG(LogLevel::DEBUG) << "[" << peer_ip << ":" << peer_port<< "]# " << buffer; // 1. 消息内容 2. 谁发的??// 2. 发消息// std::string echo_string = "server echo@ ";// echo_string += buffer;// sendto(_sockfd, result.c_str(), result.size(), 0, (struct sockaddr*)&peer, len);}}}
UdpServer.cc文件
全局定义了一个task_t类型的包装器,主函数就正常接收命令行参数,创建Route类型对象,调用单例的线程池,用tp指针指向这个线程池,然后使用智能指针指向make_unique创建的一个UdpServer对象,接收的端口号以及自定义的lambda作为参数,lambda的主体是用task_t类型对象与Route的成员函数及其参数进行绑定,也就是说bind创建了一个function<void()>类型的对象t,绑定了成员函数Route::MessageRoute和其参数,调用t()时,会自动调用MessageRoute函数,传递绑定的参数,就像星期四绑定了吃汉堡,只要是星期四,就会执行吃汉堡,不用想吃什么(传递什么参数),已经是确定好的。把这个绑定的对象作为参数放到线程池的任务队列里,等待被线程处理,执行Init函数和Start函数。
#include <iostream>
#include <memory>
#include "Route.hpp"
#include "UdpServer.hpp" // 网络通信的功能
#include "ThreadPool.hpp"using namespace ThreadPoolModule;// 仅仅是用来进行测试的
std::string defaulthandler(const std::string &message)
{std::string hello = "hello, ";hello += message;return hello;
}// 需求
// 1. 翻译系统,字符串当成英文单词,把英文单词翻译成为汉语
// 2. 基于文件来做using task_t = std::function<void()>;// ./udpserver port
int main(int argc, char *argv[])
{if(argc != 2){std::cerr << "Usage: " << argv[0] << " port" << std::endl;return 1;}// std::string ip = argv[1];uint16_t port = std::stoi(argv[1]);Enable_Console_Log_Strategy();// 1. 路由服务Route r;// 2. 线程池auto tp = ThreadPool<task_t>::GetInstance();// 3. 网络服务器对象,提供通信功能std::unique_ptr<UdpServer> usvr = std::make_unique<UdpServer>(port, [&r, &tp](int sockfd, const std::string &message, InetAddr&peer){task_t t = std::bind(Route::MessageRoute, &r, sockfd, message, peer);tp->Enqueue(t);});// std::unique_ptr<UdpServer> usvr = std::make_unique<UdpServer>(port, [&r](int sockfd, const std::string &message, InetAddr&peer){// r.MessageRoute(sockfd, message, peer);// });usvr->Init();usvr->Start();return 0;
}
Route.hpp文件
这里实现的是发送消息,以及管理在线用户
实现判断在线用户和加入用户方法
Isexist函数参数是一个InetAddr类型的,这个类管理的是客服端的端口号以及地址相关信息,端口号+地址就是一个确定的进程,也就是一个用户,把形参接收的实参与用户队列的所有用户进行比较,判断标志是端口号和地址相等就说明存在,否则就是不存在,InetAddr类重载了==,可以进行比较相等。加新用户进来,就会打印新用户的信息,然后尾插在vector中管理。删除用户通过遍历vector找到与删除用户信息一样的对象,使用erase函数进行删除。
bool IsExist(InetAddr &peer){for (auto &user : _online_user){if (user == peer){return true;}}return false;}void AddUser(InetAddr &peer){LOG(LogLevel::INFO) << "新增一个在线用户: " << peer.StringAddr();_online_user.push_back(peer);}void DeleteUser(InetAddr &peer){for (auto iter = _online_user.begin(); iter != _online_user.end(); iter++){if (*iter == peer){LOG(LogLevel::INFO) << "删除一个在线用户:" << peer.StringAddr() << "成功";_online_user.erase(iter);break;}}}// 首次给我发消息,等同于登录std::vector<InetAddr> _online_user; // 在线用户
消息发送实现
消息发送的方法需要套接字,消息内容和发送方的信息,要发送信息前提是用户,先判断是否是用户,不是就加入陌生用户到vector中管理,创建message把发送方的地址端口号和要发生的具体信息进行结合,表示谁发了什么内容出来,使用范围for把这个发给所有用户(包括发送方),有了进入也要有退出,如果发送了QUIT信息,表示退出,就会日志显示删除用户及用户信息,调用删除用户函数。
void MessageRoute(int sockfd, const std::string &message, InetAddr &peer){if (!IsExist(peer)){AddUser(peer);}std::string send_message = peer.StringAddr() + "# " + message; // 127.0.0.1:8080# 你好// TODOfor (auto &user : _online_user){sendto(sockfd, send_message.c_str(), send_message.size(), 0, (const struct sockaddr *)&(user.NetAddr()), sizeof(user.NetAddr()));}// 这个用户一定已经在线了if (message == "QUIT"){LOG(LogLevel::INFO) << "删除一个在线用户: " << peer.StringAddr();DeleteUser(peer);}}
InetAddr.hpp文件
对客服端的端口号和地址的各种处理进行封装
构造函数接收了一个类型为sockaddr_in的对象,使用 . 获取对象的成员变量进行初始化,得到了端口号和地址信息,接着是Port函数直接返回端口信息,Ip函数返回地址,NetAddr函数返回接收到的sockaddr_in结构体,实现了重载函数==,StringAddr函数返回ip和端口号结合的string类型的变量。
#pragma once
#include <iostream>
#include <string>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
// 网络地址和主机地址之间进行转换的类class InetAddr
{
public:InetAddr(struct sockaddr_in &addr) : _addr(addr){_port = ntohs(_addr.sin_port); // 从网络中拿到的!网络序列_ip = inet_ntoa(_addr.sin_addr); // 4字节网络风格的IP -> 点分十进制的字符串风格的IP}uint16_t Port() {return _port;}std::string Ip() {return _ip;}const struct sockaddr_in &NetAddr() { return _addr; }bool operator==(const InetAddr &addr){return addr._ip == _ip && addr._port == _port;}std::string StringAddr(){return _ip + ":" + std::to_string(_port);}~InetAddr(){}private:struct sockaddr_in _addr;std::string _ip;uint16_t _port;
};
UdpClient.cc文件
这里要创建两个线程,一个执行发送任务,一个执行接收任务,目的是为了保证信息不会因为c输入流没有执行而阻塞住,导致消息的滞后性,需要输入消息才能看到阻塞住的消息,所以通过两个线程一直执行输入和输出,就不会因为没有输入而看不到其它人输出的消息了,
include <iostream>
#include <string>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "Thread.hpp"int sockfd = 0;
std::string server_ip;
uint16_t server_port = 0;
pthread_t id;using namespace ThreadModlue;void Recv()
{while (true){char buffer[1024];struct sockaddr_in peer;socklen_t len = sizeof(peer);int m = recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &len);if (m > 0){buffer[m] = 0;std::cerr << buffer << std::endl; // 2}}
}
void Send()
{struct sockaddr_in server;memset(&server, 0, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(server_port);server.sin_addr.s_addr = inet_addr(server_ip.c_str());const std::string online = "inline";sendto(sockfd, online.c_str(), online.size(), 0, (struct sockaddr *)&server, sizeof(server));while (true){std::string input;std::cout << "Please Enter# "; // 1std::getline(std::cin, input); // 0int n = sendto(sockfd, input.c_str(), input.size(), 0, (struct sockaddr *)&server, sizeof(server));(void)n;if (input == "QUIT"){pthread_cancel(id);break;}}
}int main(int argc, char *argv[])
{if (argc != 3){std::cerr << "Usage: " << argv[0] << " server_ip server_port" << std::endl;return 1;}server_ip = argv[1];server_port = std::stoi(argv[2]);// 1. 创建socketsockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){std::cerr << "socket error" << std::endl;return 2;}// 2. 创建线程Thread recver(Recv);Thread sender(Send);recver.Start();sender.Start();id = recver.Id();recver.Join();sender.Join();// 2. 本地的ip和端口是什么?要不要和上面的“文件”关联呢?// 问题:client要不要bind?需要bind.// client要不要显式的bind?不要!!首次发送消息,OS会自动给client进行bind,OS知道IP,端口号采用随机端口号的方式// 为什么?一个端口号,只能被一个进程bind,为了避免client端口冲突// client端的端口号是几,不重要,只要是唯一的就行!// 填写服务器信息return 0;
}
总的流程
在server.cc文件里确定了线程池模板参数的类型是task_t,然后回调函数确定是lambda,执行start函数后会在server.hpp文件中执行回调函数_func函数,绑定t对象,入队列,enqueue函数会把这个对象放到任务队列中,然后唤醒执行wakeone函数,会执行cond的signal函数唤醒线程,需要注意的是tp是指向一个创建好的线程库,而getinstace函数内部又会指向new ThreadPool<T>(),就会调用线程池的构造函数,把Handlertask函数放到vector<Thread>中,handlertask函数会把任务队列的队头对象取出来给t,t是T t创建的,T就是task_t类型,然后t()就会执行绑定函数也就是MessageRoute函数,会发送信息出去,而队列要有任务的前提是在server.hpp文件中的recvfrom的返回值大于0,这样才能进入判断,走到回调函数,就会执行tp->Enqueue函数,所以有客服端发送消息就会入一个任务,然后线程池唤醒线程去处理这个任务,也就是把任务打出来。
相关文章:
Linux实现翻译以及群通信功能
1.翻译功能实现 UdpServer.hpp文件 构造函数 接收一个端口号和一个回调函数,回调函数是传入一个执行方法,比如翻译方法。 UdpServer(uint16_t port,func_t func):_sockfd(defaultfd),_port(port),_isrunning(false),_func(func){}Init函数 首先创建了…...
[MRCTF2020]ezpop wp
本题考点:php反序列化的pop链 首先来了解一下pop链是什么,它类似于多米诺骨牌一环套一环,要调用这个成员方法然后去找能调用这个方法的魔术方法,最后一环接一环,完成一个链子,最终形成payload。 那么来了解一下这些魔术方法 __construct() //类的构造函数࿰…...
机器学习入门之Sklearn基本操作
、 Sklearn全称:Scipy-toolkit Learn是 一个基于scipy实现的的开源机器学习库。它提供了大量的算法和工具,用于数据挖掘和数据分析,包括分类、回归、聚类等多种任务。本文我将带你了解并入门Sklearn在机器学习中的基本用法。 获取方式 pip install sc…...
(二十二)安卓开发中的数据存储之SQLite简单使用
在Android开发中,SQLite是一种非常常用的数据库存储方式。它轻量、简单,非常适合移动设备上的数据管理。本文将通过通俗易懂的语言,结合代码示例和具体场景,详细讲解SQLite在Android中的使用。 1. 什么是SQLite? SQLite是一个开…...
docker compose搭建博客wordpress
一、前言 docker安装等入门知识见我之前的这篇文章 https://blog.csdn.net/m0_73118788/article/details/146986119?fromshareblogdetail&sharetypeblogdetail&sharerId146986119&sharereferPC&sharesourcem0_73118788&sharefromfrom_link 1.1 docker co…...
信息学奥赛一本通 1498:Roadblocks | 洛谷 P2865 [USACO06NOV] Roadblocks G
【题目链接】 ybt 1498:Roadblocks 洛谷 P2865 [USACO06NOV] Roadblocks G 【题目考点】 1. 图论:严格次短路径 严格次短路的路径长度必须大于最短路的路径长度。 非严格次短路的路径长度大于等于最短路的路径长度。 【解题思路】 每个交叉路口是一…...
学习笔记—C++—类和对象(三)
目录 类和对象 再探构造函数 类型转换 隐式类型转换 显式类型转换 C语言风格类型转换 C风格类型转换 static_cast dynamic_cast const_cast reinterpret_cast static成员 友元 友元函数 友元类 友元成员函数 内部类 匿名对象 匿名对象的使用场景:…...
句句翻译。
对这些单词整理,格式为:“overall /əʊvərɔːl/ adj.全面的,综合的,总体的adv.全部,总 计,一般来说,大致上,总体上n.外套,罩衣,工装连衣裤,工装 服 ” 4,4 A review published in January in Experimental Dermatology found that ceramide made sk…...
LeetCode 2999.统计强大整数的数目:上下界数位DP
【LetMeFly】2999.统计强大整数的数目:上下界数位DP 力扣题目链接:https://leetcode.cn/problems/count-the-number-of-powerful-integers/ 给你三个整数 start ,finish 和 limit 。同时给你一个下标从 0 开始的字符串 s ,表示一…...
具身导航中的视觉语言注意力蒸馏!Vi-LAD:实现动态环境中的社会意识机器人导航
作者:Mohamed Elnoor 1 ^{1} 1, Kasun Weerakoon 1 ^{1} 1, Gershom Seneviratne 1 ^{1} 1, Jing Liang 2 ^{2} 2, Vignesh Rajagopal 3 ^{3} 3, and Dinesh Manocha 1 , 2 ^{1,2} 1,2单位: 1 ^{1} 1马里兰大学帕克分校电气与计算机工程系, 2…...
FreeRTOS入门与工程实践-基于STM32F103(一)(单片机程序设计模式,FreeRTOS源码概述,内存管理,任务管理,同步互斥与通信,队列,信号量)
裸机程序设计模式 裸机程序的设计模式可以分为:轮询、前后台、定时器驱动、基于状态机。前面三种方法都无法解决一个问题:假设有A、B两个都很耗时的函数,无法降低它们相互之间的影响。第4种方法可以解决这个问题,但是实践起来有难…...
算法思想之位运算(二)
欢迎拜访:雾里看山-CSDN博客 本篇主题:算法思想之位运算(二) 发布时间:2025.4.13 隶属专栏:算法 目录 滑动窗口算法介绍六大基础位运算符常用模板总结 例题判定字符是否唯一题目链接题目描述算法思路代码实现 汉明距离题目链接题目…...
软考笔记day04
寻址方式 CISC RISC 流水线技术 存储系统 1、层次化存储系统 2、Cache 3、主存编址计算 输入输出技术 I/O 总线...
本地电脑如何连接windows云服务器
进行远程连接需要几个数据:用户名、密码、公网IP 打开本地cmd,输入命令mstsc打开远程连接面板, 在计算机输入框中输入云服务器的IP地址 点击“选项”展开,点击“本地资源”,然后点击“详细信息” 用户名通常为admin…...
Linux内核常见的调度策略
在 Linux 内核中,调度策略决定了任务如何被分配 CPU 时间以及任务之间的优先级关系。以下是五种常见的调度策略:STOP、DL(Deadline)、RT(Real-Time)、CFS(Completely Fair Scheduler)…...
【Linux】进程优先级、进程切换、进程调度
Linux 1.进程优先级1.基本概念2.查看进程1.UID2.PRI、NI3.修改优先级(PRI) 3.竞争、独立、并行、并发 2.进程切换3.进程调度1.活动队列2.过期队列3.active、expired指针 1.进程优先级 1.基本概念 优先级:进程得到 CPU 资源分配的先后顺序。优…...
HCIP第十二天
LSA --- 链路状态通告 链路状态类型,链路状态ID,通告路由器 --- LSA的三元组 --- 可以唯一的标识出一条LSA Type --- OSPFv2中,常见的需要掌握LSA有6种 LS ID --- LSA的名字 --- 因为每一种LSA LS ID的生成方式都不相同,所以&am…...
Magnet Pro Macbook窗口分屏管理软件【提高效率工具】
Magnet Pro Macbook窗口分屏管理软件【提高效率工具】 一、介绍 Magnet Pro for Mac,是一款功能强大的窗口分屏管理软件,具有多种布局模式、窗口布局功能和其他工具,可以帮助您高效地进行多任务处理和管理工作。 拖动窗口到边缘,…...
控制单元(Control Unit, CU)
一、控制单元的定义与核心作用 控制单元 是 CPU 的核心部件之一,负责 解析指令、生成控制信号 并 协调各硬件部件 的工作时序,确保指令按预定流程正确执行。 核心定位:计算机系统的“指挥中心”,通过控制总线与运算器、存储器、…...
JavaWeb 课堂笔记 —— 10 MySQL DML + DQL
本系列为笔者学习JavaWeb的课堂笔记,视频资源为B站黑马程序员出品的《黑马程序员JavaWeb开发教程,实现javaweb企业开发全流程(涵盖SpringMyBatisSpringMVCSpringBoot等)》,章节分布参考视频教程,为同样学习…...
基于 LSTM 的多特征序列预测-SHAP可视化!
往期精彩内容: 单步预测-风速预测模型代码全家桶-CSDN博客 半天入门!锂电池剩余寿命预测(Python)-CSDN博客 超强预测模型:二次分解-组合预测-CSDN博客 VMD CEEMDAN 二次分解,BiLSTM-Attention预测模型…...
【C++】哈希扩展海量数据处理
目录 位图 位图面试题 C库中的位图bitset 位图优缺点 位图相关题目 布隆过滤器 布隆过滤器的介绍 布隆过滤器的应用 海量数据处理 位图 位图面试题 1.给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个整数是否在这40亿…...
考研数据结构精讲:数组与特殊矩阵的压缩存储技巧(包含真题及解析)
考研数据结构精讲:数组与特殊矩阵的压缩存储技巧 一、数组基础概念 1.1 数组的定义 数组是由相同数据类型的元素构成的有限序列,具有以下核心特性: 维度特性:支持一维到多维结构(常见二维数组)随机访问…...
【Android】ContentResolver的使用
在 Android 中,ContentResolver 是一个非常重要的类,它提供了与 ContentProvider 进行交互的方法。ContentProvider 是用于在不同应用程序之间共享数据的标准接口,而 ContentResolver 则是从客户端(如 Activity 或 Service&#x…...
Python 的 collections 模块
1. deque (双端队列) 定义 deque(读作 “deck”,即双端队列)是一个支持从两端高效添加和删除元素的数据结构。相比列表(list)在头部操作的 O(n) 时间复杂度,deque 的两端操作都是 O(1)。 用途 队列和栈…...
浏览器发起调用到服务器的全过程解析
在 Web 应用的交互过程中,从用户在浏览器输入 URL 发起请求,到最终获取服务器返回的内容,背后涉及多个复杂而有序的步骤。理解这一过程,对于深入掌握 Web 开发、优化应用性能以及排查网络问题都具有重要意义。下面将详细阐述浏览器…...
塑料瓶识别分割数据集labelme格式976张1类别
数据集格式:labelme格式(不包含mask文件,仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数):976 标注数量(json文件个数):976 标注类别数:1 标注类别名称:["Trash plastic"] 每个类别标注的框数…...
RuoYi-Vue升级为https访问-后端安装SSL证书(单台Linux服务器部署)
一、前言 当Nginx已经作为反向代理并成功配置了SSL证书时,前端客户端与Nginx的通信已经是加密的。但Nginx和后端服务之间的连接可能仍然存在明文传输的风险。 如果Nginx和后端服务位于同一台物理机器或者通过安全的内部网络(如私有VLAN或防火墙保护的内网)进行通信,则可以…...
【学习笔记】文件上传漏洞--中间件解析漏洞、编辑器安全
目录 一、IIS 二、Apache HTTP Server 三、Apache HTTPD 未知后缀解析漏洞 四、Apache HTTPD 换行解析漏洞 五、黑、白名单 六、nginx解析漏洞 七、编辑器漏洞 一、IIS 文件夹 正常:image/qq.jpg 执行:image.asp/qq.jpg qq.jpg就会被当做asp解…...
【论文阅读】UniAD: Planning-oriented Autonomous Driving
一、Introduction 传统的无人驾驶采用了区分子模块的设计,即将无人驾驶拆分为感知规划控制三个模块,这虽然能够让无人驾驶以一个很清晰的结构实现,但是感知的结果在传达到规划部分的时候,会导致部分信息丢失,这势必会…...
【第16届蓝桥杯C++C组】--- 数位倍数
Hello呀,小伙伴们,第16届蓝桥杯也完美结束了,无论大家考的如何,都要放平心态,今年我刚上大一,也第一次参加蓝桥杯,刷的算法题也只有200来道,但是还是考的不咋滴,但是拿不…...
【腾讯云智】20250329笔试算法题
文章目录 第一题1. 题目描述2. 思路解析3. AC代码 第二题1. 题目描述2. 思路解析3. AC代码 第三题1. 题目描述2. 思路解析3. AC代码 第一题 1. 题目描述 题目链接:牛牛的水果店 2. 思路解析 这题比较简单,按数学思维把题目的意思翻译过来就是给你一…...
【2025最新】windows本地部署LightRAG,完成neo4j知识图谱保存
之前在服务器部署neo4j失败,无奈只能在本地部署,导致后期所有使用的知识图谱数据都存在本地,这里为了节省时间,先在本地安装LigthRAG完成整个实验流程,后续在学习各种服务器部署和端口调用。从基础和简单的部分先做起来…...
思考力提升的黄金标准:广度、深度与速度的深度剖析
文章目录 引言一、广度的拓展:构建多元知识网络1.1 定义与重要性1.2 IT技术实例与提升策略小结:构建多元知识网络,提升IT领域思考力广度 二、深度的挖掘:追求知识的精髓2.1 定义与重要性2.2 IT技术实例与提升策略小结:…...
7个向量数据库对比:Milvus、Pinecone、Vespa、Weaviate、Vald、GSI 和 Qdrant
7个向量数据库对比:Milvus、Pinecone、Vespa、Weaviate、Vald、GSI 和 Qdrant 本文简要总结了当今市场上正在积极开发的7个向量数据库,Milvus、Pinecone、Vespa、Weaviate、Vald、GSI 和 Qdrant 的详细比较。 我们已经接近在搜索引擎体验的基础层面上涉…...
计算机组成原理笔记(十五)——3.5指令系统的发展
不同类型的计算机有各具特色的指令系统,由于计算机的性能、机器结构和使用环境不同,指令系统的差异也是很大的。 3.5.1 x86架构的扩展指令集 x86架构的扩展指令集是为了增强处理器在多媒体、三维图形、并行计算等领域的性能而设计的。这些扩展指令集通…...
Rust 中的Relaxed 内存指令重排演示:X=0 Y=0 是怎么出现的?
🔥 Rust 中的内存重排演示:X0 && Y0 是怎么出现的? 在并发编程中,我们经常会听说“内存重排(Memory Reordering)”这个术语,但它似乎总是只出现在理论或者别人口中的幻觉里。本文将通过…...
vp 2023 icpc 合肥 解题补题记录 [F E J G]
gym 链接: https://codeforces.com/gym/104857 F. Colorful Balloons 血签, 用 map 存一下每个颜色气球出现的次数, 找出出现次数大于一半的颜色. #include<bits/stdc.h> using namespace std;#define int long long #define endl \nsigned main() {int n;cin >> …...
学习SqlSugar的跨库查询基本用法
使用SqlSugar操作数据库通常都是单库操作,跨库查询的情况要么是单个系统数据不完整,需要其它系统的关联业务数据支撑,要么就是需要整合汇总多个系统的数据进行数据数据分析、处理、展示。遇到上述情况,可以要求另外的系统提供查询…...
智慧工厂可视化系统,赋能工业生产智能化升级
借助图扑软件 HT 搭建智慧工厂可视化系统。利用先进 3D 建模,对工厂布局、设备运行、生产流程进行逼真复刻。实时展示设备状态、生产进度、质量检测数据等,助力管理者精准洞察生产,高效决策,推动工厂智能化转型。...
案例驱动的 IT 团队管理:创新与突破之路: 第四章 危机应对:从风险预见到创新破局-4.1.2债务评估模型与优先级排序
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 4.1.2 技术债务评估模型与优先级排序:构建智能决策体系一、技术债务的"冰山效应"与量化困境二、三维评估模型:穿透债务迷雾的探照灯2.1 评…...
nfs共享目录主配置文件权限参数
/etc/exports 文件默认为空文件,需要输入nfs共享命令 格式:共享目录的路径 允许访问的NFS客户端(共享权限参数) #编辑共享目录配置文件(即/etc/exports) [rootserver ~]# mkdir /nfs_share (创建共享的目录…...
C++ 编程指南35 - 为保持ABI稳定,应避免模板接口
一:概述 模板在 C 中是编译期展开的,不同模板参数会生成不同的代码,这使得模板类/函数天然不具备 ABI 稳定性。为了保持ABI稳定,接口不要直接用模板,先用普通类打个底,模板只是“外壳”,这样 AB…...
探索 MCP 和 A2A 协议: 本质上新协议都基于 HTTP的
以下是以 CSDN 博客的形式记录你对 MCP 协议和 A2A 协议数据传递的理解,重点探讨了它们为何基于 HTTP 协议、HTTP 的优势,以及数据传输的本质。文章面向技术社区,结构清晰,适合分享。 探索 MCP 和 A2A 协议:为何新协议…...
Linux网络http与https
应用层协议HTTP 提示 因为现在大多数都是https,所以就用https来介绍http,https比http多了一个加密功能,不影响介绍http。 什么是http 虽然我们说, 应用层协议是我们程序猿自己定的. 但实际上, 已经有大佬们定义了一些现成的, 又非常好用的…...
C++ 算法(2):STL list 完全解析,从入门到高效使用
1. list概述 std::list是C标准模板库(STL)中的一个双向链表容器。与vector和deque不同,list不支持随机访问,但它在任何位置插入和删除元素都非常高效,时间复杂度为O(1)。 2. list的基本特性 双向链表结构:每个元素都包含指向前驱…...
【Linux实践系列】:匿名管道收尾+完善shell外壳程序
🔥 本文专栏:Linux Linux实践项目 🌸作者主页:努力努力再努力wz 💪 今日博客励志语录: 人生总会有自己能力所不及的范围,但是如果你在你能力所及的范围尽了全部的努力,那你还有什么遗…...
Linux基本指令2
1.head 查看文件的前面内容 head 路径 :查看路径开头部分内容,如下图:head /var/log/messages查看/var/log/messages这个日志中前面内容 head -数字 路径 :查看路径开头指定数字行部分内容,如下图:he…...
Tkinter使用Canvas绘制图形
在Tkinter中,Canvas是一个非常强大的控件,用于绘制图形、显示图片和实现自定义图形界面。通过Canvas,您可以绘制各种形状、线条、文本等,并且能够进行灵活的动画和交互。掌握Canvas的使用将使您能够创建丰富的图形界面。 8.1 创建Canvas控件 Canvas控件是一个区域,用于绘…...
CF985G Team Players
我敢赌,就算你知道怎么做,也必然得调试半天才能 AC。 [Problem Discription] \color{blue}{\texttt{[Problem Discription]}} [Problem Discription] 图片来自洛谷。 [Analysis] \color{blue}{\texttt{[Analysis]}} [Analysis] 显然不可能正面计算。所以…...