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

【Linux网络】epoll实现的echo服务器{nocopy类/智能指针/echo服务器}

文章目录

  • 1.代码基础
    • 1.1某类唯一存在
    • 1.2C++智能指针
  • 2.epoll实现的echo服务器
    • 日志
    • 套接字
    • CMake
    • epoll封装
    • 主函数
    • 服务器

1.代码基础

1.1某类唯一存在

这段代码定义了一个名为 nocopy 的类,它旨在防止该类的实例被复制或赋值。这是通过在类中显式删除拷贝构造函数(nocopy(const nocopy &))和赋值操作符(const nocopy &operator=(const nocopy &))来实现的。

拷贝构造函数(Copy Constructor)
拷贝构造函数是一种特殊的构造函数,用于创建一个新对象作为另一个同类型对象的副本。在 nocopy 类中,拷贝构造函数被声明为 = delete,这意味着如果尝试使用拷贝构造函数来创建 nocopy 类的实例的副本,编译器将报错。这确保了 nocopy 类的实例不能通过拷贝构造函数进行复制。

赋值操作符(Assignment Operator)
赋值操作符用于将一个对象的状态(即其成员变量的值)复制到另一个同类型的对象。同样地,在 nocopy 类中,赋值操作符也被声明为 = delete,这意味着如果尝试将一个 nocopy 类的实例赋值给另一个同类型的实例,编译器将报错。这确保了 nocopy 类的实例不能通过赋值操作符进行赋值。

使用场景
资源管理:当类的实例管理着重要的资源(如文件句柄、网络连接、动态分配的内存等)时,可能需要防止这些资源被无意中复制或赋值,以避免资源泄露或不可预测的行为。
唯一性保证:在需要确保某个类的实例在程序中唯一存在的场景中,禁用拷贝和赋值操作可以强制实现这一点。

示例
cpp
#include <iostream>  class nocopy  
{  
public:  nocopy() { std::cout << "nocopy constructed\n"; }  nocopy(const nocopy &) = delete;  const nocopy &operator=(const nocopy &) = delete;  
};  int main() {  nocopy obj1; // 正确:调用构造函数  // nocopy obj2 = obj1; // 错误:拷贝构造函数被删除  // obj1 = obj2; // 错误:赋值操作符被删除  return 0;  
}

在这个示例中,尝试使用拷贝构造函数或赋值操作符会导致编译错误,因为它们都已被删除。

当一个类(如你提供的nocopy类)被设计成不允许被拷贝(通过拷贝构造函数)或赋值(通过赋值运算符),这通常是为了确保该类的实例在程序中的唯一性或特定的生命周期管理策略。当其他类继承这个nocopy类时,它们也继承了这些不允许拷贝和赋值的特性,这带来了几个重要的意义和目的:

  1. 防止浅拷贝问题:对于包含动态分配资源(如指针指向的内存、文件句柄等)的类,如果允许拷贝,可能会导致多个对象实例共享相同的资源,从而引发数据竞争、资源泄露等问题。通过禁止拷贝,可以确保每个对象都管理自己独立的资源,从而避免这些问题。
  2. 实现单例模式:单例模式是一种确保类只有一个实例,并提供一个全局访问点的设计模式。通过继承nocopy类,可以很容易地实现一个单例类,因为它自然就不允许通过拷贝来创建额外的实例。
  3. 确保对象唯一性:在某些情况下,可能希望确保某个类的所有实例在逻辑上都是唯一的,或者至少在某些方面(如标识符、配置等)是唯一的。通过禁止拷贝和赋值,可以强制要求使用其他机制(如工厂方法、依赖注入等)来创建和管理这些对象的实例,从而有助于维护这种唯一性。
  4. 强化不可变性和线程安全:对于设计为不可变(immutable)的类,禁止拷贝和赋值可以进一步强调其不可变性,因为任何尝试修改实例(通过赋值)或创建其副本(通过拷贝)的行为都将被编译器阻止。此外,不可变对象通常更容易实现线程安全,因为它们不需要在并发访问时进行同步。
  5. 简化资源管理和生命周期:通过控制对象的拷贝和赋值行为,可以更精确地控制资源的分配和释放时机,以及对象的生命周期。这对于管理复杂资源(如网络连接、数据库连接等)的类尤为重要。
  6. 表达设计意图:通过明确禁止拷贝和赋值,类的设计者可以向使用该类的其他开发者传达关于对象如何被预期使用和管理的明确信息。这有助于减少误解和错误使用,提高代码的可维护性和可读性。
    总之,通过让其他类继承nocopy类并继承其不允许拷贝和赋值的特性,可以在多个方面提高代码的健壮性、安全性和可维护性。

1.2C++智能指针

C++标准库提供的一种用于自动管理动态分配内存的指针类型。它们的主要目的是解决传统裸指针(raw pointers)在动态内存管理时容易出现的内存泄漏、重复释放等问题。智能指针通过封装裸指针并提供自动的析构函数来确保动态分配的内存被适时释放,从而简化了内存管理。

C++标准库中主要有以下几种智能指针:

std::unique_ptr:

独享所有权的智能指针。 std::unique_ptr不允许拷贝构造和拷贝赋值,但支持移动构造和移动赋值。 这意味着一个std::unique_ptr对象在任意时刻只能被一个std::unique_ptr拥有。当std::unique_ptr被销毁时(例如,离开作用域),它所指向的对象也会被自动删除。

std::shared_ptr:

共享所有权的智能指针。 多个std::shared_ptr实例可以指向同一个对象,并通过内部的控制块(通常是一个计数器)来跟踪有多少std::shared_ptr指向该对象。当最后一个指向该对象的std::shared_ptr被销毁时,对象才会被删除。std::shared_ptr支持拷贝构造和拷贝赋值,这使得它们非常适合在复杂的数据结构或算法中共享所有权。

std::weak_ptr:

std::weak_ptr是一种不拥有其所指对象的智能指针。它主要用于解决std::shared_ptr之间的循环引用问题。std::weak_ptr可以指向一个由std::shared_ptr管理的对象,但它不增加对象的共享计数。因此,当所有的std::shared_ptr都被销毁时,即使还有std::weak_ptr指向该对象,对象也会被销毁。std::weak_ptr提供了一个lock成员函数,用于尝试获取一个指向对象的std::shared_ptr,如果对象还存在,则返回一个有效的std::shared_ptr;否则,返回一个空的std::shared_ptr。

智能指针的使用使得C++中的动态内存管理更加安全和方便,减少了内存泄漏和野指针的风险。然而,开发者仍然需要谨慎使用它们,特别是在复杂的所有权关系和生命周期管理中。
复习好文!

2.epoll实现的echo服务器

日志

#pragma once#include <iostream>
#include <time.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>#define SIZE 1024#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4#define Screen 1
#define Onefile 2
#define Classfile 3#define LogFile "log.txt"class Log
{
private:int printMethod;std::string path;public:Log(){printMethod = Screen;path = "./";}void Enable(int method){printMethod = method;}std::string levelToString(int level){switch (level){case Info:return "Info";case Debug:return "Debug";case Warning:return "Warning";case Error:return "Error";case Fatal:return "Fatal";default:return "None";}}/*void logmessage(int level, const char *format, ...){time_t t = time(nullptr);struct tm *ctime = localtime(&t);char leftbuffer[SIZE];snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,ctime->tm_hour, ctime->tm_min, ctime->tm_sec);va_list s;va_start(s, format);char rightbuffer[SIZE];vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);va_end(s);// 格式:默认部分+自定义部分char logtxt[SIZE * 2];snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);// printf("%s", logtxt);printLog(level, logtxt);}*/// lg(Warning, "accept error, %s: %d", strerror(errno), errno);void operator()(int level, const char *msg_format, ...){time_t timestamp = time(nullptr);struct tm *ctime = localtime(&timestamp);//level 年月日char leftbuffer[SIZE];snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,ctime->tm_hour, ctime->tm_min, ctime->tm_sec);//自定义msgva_list arg_list;//存储可变参数列表信息va_start(arg_list, msg_format);//初始化 使其指向函数参数列表中format参数之后的第一个可变参数char rightbuffer[SIZE];vsnprintf(rightbuffer, sizeof(rightbuffer), msg_format, arg_list);va_end(arg_list);//清理va_list变量// 格式:默认部分+自定义部分char log_content[SIZE * 2];snprintf(log_content, sizeof(log_content), "%s %s", leftbuffer, rightbuffer);// printf("%s", logtxt); // 暂时打印printLog(level, log_content);}void printLog(int level, const std::string &log_content){switch (printMethod){case Screen:std::cout << log_content << std::endl;break;case Onefile:printOneFile(LogFile, log_content);break;case Classfile:printClassFile(level, log_content);break;default:break;}}void printOneFile(const std::string &log_filename, const std::string &log_content){//path = "./"; #define LogFile "log.txt"std::string _logFilename = path + log_filename;int fd = open(_logFilename.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666); // "log.txt"if (fd < 0)return;write(fd, log_content.c_str(), log_content.size());close(fd);}void printClassFile(int level, const std::string &log_content){//#define LogFile "log.txt"std::string filename = LogFile;filename += ".";filename += levelToString(level); // "log.txt.Debug"printOneFile(filename, log_content);}~Log(){}
};Log lg;/*
int sum(int n, ...)
{va_list s; // char*va_start(s, n);int sum = 0;while(n){sum += va_arg(s, int); // printf("hello %d, hello %s, hello %c, hello %d,", 1, "hello", 'c', 123);n--;}va_end(s); //s = NULLreturn sum;
}
*/

套接字

#pragma once#include <iostream>
#include <string>
#include <unistd.h>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "Log.hpp"enum
{SocketErr = 2,BindErr,ListenErr,
};const int g_backlog = 10;class Sock
{
private:int _sockfd;public:Sock(){}~Sock(){}public:void Socket(){_sockfd = socket(AF_INET, SOCK_STREAM, 0);if (_sockfd < 0){lg(Fatal, "socker error, %s: %d", strerror(errno), errno);exit(SocketErr);}}void Bind(uint16_t port){struct sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(port);local.sin_addr.s_addr = INADDR_ANY;if (bind(_sockfd, (struct sockaddr *)&local, sizeof(local)) < 0){lg(Fatal, "bind error, %s: %d", strerror(errno), errno);exit(BindErr);}}void Listen(){if (listen(_sockfd, g_backlog) < 0){lg(Fatal, "listen error, %s: %d", strerror(errno), errno);exit(ListenErr);}}int Accept(std::string *clientip, uint16_t *clientport){struct sockaddr_in peer;socklen_t len = sizeof(peer);int newfd = accept(_sockfd, (struct sockaddr *)&peer, &len);if (newfd < 0){lg(Warning, "accept error, %s: %d", strerror(errno), errno);return -1;}char ipstr[64];inet_ntop(AF_INET, &peer.sin_addr, ipstr, sizeof(ipstr));*clientip = ipstr;*clientport = ntohs(peer.sin_port);return newfd;}bool Connect(const std::string &ip, const uint16_t &port){struct sockaddr_in peer;memset(&peer, 0, sizeof(peer));peer.sin_family = AF_INET;peer.sin_port = htons(port);inet_pton(AF_INET, ip.c_str(), &(peer.sin_addr));int n = connect(_sockfd, (struct sockaddr *)&peer, sizeof(peer));if (n == -1){std::cerr << "connect to " << ip << ":" << port << " error" << std::endl;return false;}return true;}void CloseFd(){close(_sockfd);}int getSocketFd(){return _sockfd;}
};

CMake

cmake_minimum_required(VERSION 3.29)
set(CMAKE_CXX_STANDARD 11)  
set(CMAKE_CXX_STANDARD_REQUIRED True)project(EpollServer)add_executable(epoll_server Main.cc)

epoll封装

#pragma once#include "nocopy.hpp"
#include "Log.hpp"
#include <cerrno>
#include <cstring>
#include <sys/epoll.h>class Epoller : public nocopy
{static const int size = 128;private:int _epollFd;int _timeout{3000};public:Epoller(){_epollFd = epoll_create(size);if (_epollFd == -1)lg(Error, "epoll_create error: %s", strerror(errno));elselg(Info, "epoll_create success: %d", _epollFd);}int EpllerUpdate(int oper, int sock, uint32_t event){// int epoll_ctl(int __epfd, int __op, int __fd, epoll_event *)int n = 0;if (oper == EPOLL_CTL_DEL){n = epoll_ctl(_epollFd, oper, sock, nullptr);if (n != 0)lg(Error, "epoll_ctl delete error!");}else // EPOLL_CTL_MOD || EPOLL_CTL_ADD{/*typedef union epoll_data{void *ptr;int fd;uint32_t u32;uint64_t u64;} epoll_data_t;struct epoll_event{uint32_t events;   // Epoll eventsepoll_data_t data; // User data variable} __EPOLL_PACKED;*/struct epoll_event ev;ev.events = event;ev.data.fd = sock; // 方便后期得知 是哪一个fd就绪了n = epoll_ctl(_epollFd, oper, sock, &ev);if (n != 0)lg(Error, "epoll_ctl error!");}return n;}int EpollerWait(struct epoll_event revents[], int num){// int epoll_wait(int __epfd, epoll_event *__events, int __maxevents, int __timeout)int n = epoll_wait(_epollFd, revents, num, /*_timeout 0*/ -1);return n;}~Epoller(){if (_epollFd >= 0)close(_epollFd);}
};

主函数

#include <iostream>
#include <memory>
#include "EpollServer.hpp"int main()
{std::unique_ptr<EpollServer> epoll_svr(new EpollServer(8888));epoll_svr->Init();epoll_svr->Start();/*//无法引用 函数 "Epoller::Epoller(const Epoller &)" (已隐式声明) -- 它是已删除的函数Epoller ep;Epoller ep1 = ep;*/return 0;
}

服务器

#pragma once#include <iostream>
#include <memory>
#include <sys/epoll.h>
#include "Socket.hpp"
#include "Epoller.hpp"
#include "Log.hpp"
#include "nocopy.hpp"uint32_t EVENT_IN = (EPOLLIN);
uint32_t EVENT_OUT = (EPOLLOUT);// 此程序的read/write仍忽略了网络读取报文完整性问题 主要考虑epoll逻辑
class EpollServer : public nocopy
{static const int num = 64;private:std::shared_ptr<Epoller> _epollerPtr;std::shared_ptr<Sock> _listenSocketPtr;uint16_t _port;public:EpollServer(uint16_t port): _port(port),_listenSocketPtr(new Sock()),_epollerPtr(new Epoller()){}void Init(){_listenSocketPtr->Socket();_listenSocketPtr->Bind(_port);_listenSocketPtr->Listen();lg(Info, "create listen socket success: %d\n", _listenSocketPtr->getSocketFd());}void Accepter() // 获取了一个新连接{std::string clientip;uint16_t clientport;int sock = _listenSocketPtr->Accept(&clientip, &clientport);if (sock > 0){// 不能直接读取 原因select/poll已讲_epollerPtr->EpllerUpdate(EPOLL_CTL_ADD, sock, EVENT_IN);lg(Info, "get a new link, client info@ %s:%d", clientip.c_str(), clientport);}}void Recver(int fd){char buffer[1024];// 1.不一定是完整的报文// 2.读到部分报文 下次的Recver()函数中buffer是局部变量 // A报文如果发两次过来 也无法拼接成完整报文ssize_t n = read(fd, buffer, sizeof(buffer) - 1);if (n > 0){buffer[n] = 0;std::cout << "get a messge: " << buffer << std::endl;std::string echo_str = "server echo $ ";echo_str += buffer;write(fd, echo_str.c_str(), echo_str.size());}else if (n == 0){lg(Info, "client quit, me too, close fd is : %d", fd);_epollerPtr->EpllerUpdate(EPOLL_CTL_DEL, fd, 0);close(fd);}else{lg(Warning, "recv error: fd is : %d", fd);_epollerPtr->EpllerUpdate(EPOLL_CTL_DEL, fd, 0);close(fd);}}void Dispatcher(struct epoll_event revs[], int num){for (int i = 0; i < num; i++){uint32_t events = revs[i].events;int fd = revs[i].data.fd;if (events & EVENT_IN) // 客户联连接读取事件就绪{if (fd == _listenSocketPtr->getSocketFd())Accepter();else // 普通读取事件就绪Recver(fd);}// else if (events & EVENT_OUT){}// else{}}}void Start(){// 将listensock添加到epoll中 -> listensock和他关心的事件 添加到内核epoll模型中rb_tree_epollerPtr->EpllerUpdate(EPOLL_CTL_ADD, _listenSocketPtr->getSocketFd(), EVENT_IN);struct epoll_event revs[num];for (;;){int n = _epollerPtr->EpollerWait(revs, num);if (n > 0) // 有事件就绪{lg(Debug, "event happened, first event fd is : %d", revs[0].data.fd);Dispatcher(revs, n);}else if (n == 0)lg(Info, "time out ...");elselg(Error, "epll wait error");}}~EpollServer(){_listenSocketPtr->CloseFd();}
};

相关文章:

【Linux网络】epoll实现的echo服务器{nocopy类/智能指针/echo服务器}

文章目录 1.代码基础1.1某类唯一存在1.2C智能指针 2.epoll实现的echo服务器日志套接字CMakeepoll封装主函数服务器 1.代码基础 1.1某类唯一存在 这段代码定义了一个名为 nocopy 的类&#xff0c;它旨在防止该类的实例被复制或赋值。这是通过在类中显式删除拷贝构造函数&#…...

[数据集][目标检测]拐杖检测数据集VOC+YOLO格式2778张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2778 标注数量(xml文件个数)&#xff1a;2778 标注数量(txt文件个数)&#xff1a;2778 标注…...

长按加速- 解决react - setInterval下无法更新问题

最开始直接setInterval里&#xff0c;useState硬写&#xff0c;发现更新不&#xff0c;固定值 换let&#xff0c;发现dom更新不了 正确做法是用ref 并且pc端可以长按的&#xff0c;只是要用onTouchStart&#xff0c;不要用onMouseDown onTouchStart{handleMouseDown} onTou…...

路网双线合并单线——ArcGIS 解决方法

路网双线合并成单线是一个在地图制作、交通规划以及GIS分析中常见的需求。双线路网定义&#xff1a;具有不同流向、不同平面结构的道路。此外&#xff0c;车道数较多的道路&#xff08;例如&#xff0c;双黄实线车道数大于4的道路&#xff09;也可以视为双线路网&#xff0c;本…...

【.NET全栈】ASP.NET开发Web应用——ADO.NET数据访问技术

文章目录 前言一、ADO.NET基础1、ADO.NET架构2、ADO.NET数据提供者 二、连接数据库1、SqlConnection数据库连接类2、使用SqlConnectionStringBuilder连接字符串3、关闭和释放连接4、在web.config配置文件中保存连接字符串5、连接池技术 三、与数据库交互1、使用SqlCommand操作数…...

【机器学习】无监督学习和自监督学习

1. 什么是机器学习 机器学习是一种使计算机系统能够从数据中学习并做出预测或决策的技术和科学领域。它不需要显式地编程来执行特定任务&#xff0c;而是通过使用算法来分析数据和识别模式&#xff0c;以此“学习”如何做出准确的预测或决策。 以下是机器学习的几个关键点&…...

蓝牙新篇章:WebKit的Web Bluetooth API深度解析

蓝牙新篇章&#xff1a;WebKit的Web Bluetooth API深度解析 在物联网(IoT)时代&#xff0c;Web应用与物理设备的交互变得越来越重要。WebKit的Web Bluetooth API开启了一个新时代&#xff0c;允许Web页面直接与蓝牙设备通信。这一API不仅提高了用户体验&#xff0c;还为创新的…...

2024可信数据库发展大会:TDengine CEO 陶建辉谈“做难而正确的事情”

在当前数字经济快速发展的背景下&#xff0c;可信数据库技术日益成为各行业信息化建设的关键支撑点。金融、电信、能源和政务等领域对数据处理和管理的需求不断增加&#xff0c;推动了数据库技术的创新与进步。与此同时&#xff0c;人工智能与数据库的深度融合、搜索与分析型数…...

Guns v7.3.0:基于 Vue3、Antdv 和 TypeScript 打造的开箱即用型前端框架

摘要 本文深入探讨了Guns v7.3.0前端项目&#xff0c;该项目是基于Vue3、Antdv和TypeScript的前端框架&#xff0c;以Vben Admin的脚手架为基础进行了改造。文章分析了Guns 7.3.0的技术特点&#xff0c;包括其使用Vue3、vite2和TypeScript等最新前端技术栈&#xff0c;以及提供…...

掌握构建艺术:在Gradle中配置自定义的源代码管理(SCM)

掌握构建艺术&#xff1a;在Gradle中配置自定义的源代码管理&#xff08;SCM&#xff09; 在软件开发过程中&#xff0c;源代码管理&#xff08;Source Code Management&#xff0c;简称SCM&#xff09;是不可或缺的一部分。它帮助开发者管理代码的变更历史&#xff0c;支持团…...

如何在 Mac 上下载安装植物大战僵尸杂交版? 最新版本 2.2 详细安装运行教程问题详解

植物大战僵尸杂交版已经更新至2.2了&#xff0c;但作者只支持 Windows、手机等版本并没有支持 MAC 版本&#xff0c;最近搞到了一个最新的杂交 2.2 版本的可以在 Macbook 上安装运行的移植安装包&#xff0c;试了一下非常完美能够正常在 MAC 上安装运行&#xff0c;看图&#x…...

​前端Vue组件技术实践:打造自定义精美悬浮菜单按钮组件

随着前端技术的迅猛发展&#xff0c;复杂的应用场景和不断迭代的产品需求使得开发的复杂度日益提升。传统的整体式开发方式已经难以满足现代前端应用的灵活性和可维护性需求。在这样的背景下&#xff0c;组件化开发逐渐崭露头角&#xff0c;成为解决复杂前端应用问题的有效手段…...

数据仓库的一致性维度

一致性维度的定义&#xff1a; 一致性维度是指在数据仓库中&#xff0c;具有相同属性和含义的维度在不同的事实表中保持一致。它确保了通过不同事实表进行查询和分析时&#xff0c;维度数据的一致性和准确性。 一致性维度的作用&#xff1a; 数据一致性&#xff1a;一致性维度…...

【ffmpeg命令】RTMP推流

文章目录 前言推流是什么RTMP协议简介RTMP的基本概念RTMP的工作原理RTMP的优缺点 ffmpeg RTMP推流推流命令综合解释ffplay播放RTMP流 总结 前言 在现代的视频直播中&#xff0c;RTMP&#xff08;Real-Time Messaging Protocol&#xff09;是一种广泛使用的流媒体传输协议。它允…...

人工智能大模型发展的新形势及其省思

作者简介 肖仰华&#xff0c;复旦大学计算机科学技术学院教授、博导&#xff0c;上海市数据科学重点实验室主任。研究方向为知识图谱、知识工程、大数据管理与挖掘。主要著作有《图对称性理论及其在数据管理中的应用》、《知识图谱&#xff1a;概念与技术》&#xff08;合著&a…...

Linux云计算 |【第一阶段】SERVICES-DAY4

主要内容&#xff1a; DHCP概述、PXE批量装机、配置PXE引导、Kickstart自动应答、Cobbler装机平台 一、DHCP服务概述及原理 DHCP动态主机配置协议&#xff08;Dynamic Host Configuration Protocol&#xff09;&#xff0c;由IETF&#xff08;Internet网络工程师任务小组&…...

微信小程序 button样式设置为图片的方法

微信小程序 button样式设置为图片的方法 background-image background-size与background-repeat与border:none;是button必须的 <view style" position: relative;"><button class"customer-service-btn" style"background-image: url(./st…...

2024 HNCTF PWN(hide_flag Rand_file_dockerfile Appetizers TTOCrv_)

文章目录 参考hide_flag思路exp Rand_file_dockerfile libc 2.31思路exp Appetizers glibc 2.35绕过关闭标准输出实例客户端 关闭标准输出服务端结果exp TTOCrv_&#x1f3b2; glibc 2.35逆向DT_DEBUG获得各个库地址随机数思路exp 参考 https://docs.qq.com/doc/p/641e8742c39…...

《昇思25天学习打卡营第25天|第14天》

今天是打卡的第十四天&#xff0c;今天学习的是应用实践中的热门LLM及其他AI应用的K近邻算法实现红酒分类篇。这一片主要介绍使用MindSpore在部分wine数据集上进行KNN实验&#xff0c;对实验的步骤的介绍&#xff1a;K近邻算法原理介绍&#xff08;分类问题、回归问题和距离的定…...

Easysearch、Elasticsearch、Amazon OpenSearch 快照兼容对比

在当今的数据驱动时代&#xff0c;搜索引擎的快照功能在数据保护和灾难恢复中至关重要。本文将对 EasySearch、Elasticsearch 和 Amazon OpenSearch 的快照兼容性进行比较&#xff0c;分析它们在快照创建、恢复、存储格式和跨平台兼容性等方面的特点&#xff0c;帮助大家更好地…...

数据分析入门指南:数据库入门(五)

本文将总结CDA认证考试中数据库中部分知识点&#xff0c;内容来源于《CDA模拟题库与备考资料PPT》 。 CDA认证&#xff0c;作为源自中国、面向全球的专业技能认证&#xff0c;覆盖金融、电信、零售、制造、能源、医疗医药、旅游、咨询等多个行业&#xff0c;旨在培养能够胜任数…...

Logback日志异步打印接入指南,输出自定义业务数据

背景 随着应用的请求量上升&#xff0c;日志输出量也会成线性比例的上升&#xff0c;给磁盘IO带来压力与性能瓶颈。应用也遇到了线程池满&#xff0c;是因为大量线程卡在输出日志。为了缓解日志同步打印&#xff0c;会采取异步打印日志。这样会引起日志中的追踪id丢失&#xf…...

将iPad 作为Windows电脑副屏的几种方法(二)

将iPad 作为Windows电脑副屏的几种方法&#xff08;二&#xff09; 1. 前言2. EV 扩展屏2.1 概述2.2 下载、安装、连接教程2.3 遇到的问题和解决方法2.3.1 平板连接不上电脑 3. Twomon SE3.1 概述3.2 下载安装教程 4. 多屏中心&#xff08;GlideX&#xff09;4.1 概述4.2 下载安…...

[word] word表格跨页断开实现教程 #职场发展#媒体

word表格跨页断开实现教程 选中整个word表格 单击鼠标右键&#xff0c;选择“表格属性”选项 切换至“行”标签&#xff0c;找到“允许跨页断行”选项 勾选上“允许跨页断行”&#xff0c;单击“确定”按钮&#xff0c;完成&#xff01; word表格跨页断开实现教程的下载地址&a…...

《Linux运维总结:基于ARM64架构CPU使用docker-compose一键离线部署单机版tendis2.4.2》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;《Linux运维篇&#xff1a;Linux系统运维指南》 一、部署背景 由于业务系统的特殊性&#xff0c;我们需要面对不同的客户部署业务系统&#xff0…...

【Apache Doris】周FAQ集锦:第 14 期

【Apache Doris】周FAQ集锦&#xff1a;第 14 期 SQL问题数据操作问题运维常见问题其它问题关于社区 欢迎查阅本周的 Apache Doris 社区 FAQ 栏目&#xff01; 在这个栏目中&#xff0c;每周将筛选社区反馈的热门问题和话题&#xff0c;重点回答并进行深入探讨。旨在为广大用户…...

Log4j的原理及应用详解(四)

本系列文章简介&#xff1a; 在软件开发的广阔领域中&#xff0c;日志记录是一项至关重要的活动。它不仅帮助开发者追踪程序的执行流程&#xff0c;还在问题排查、性能监控以及用户行为分析等方面发挥着不可替代的作用。随着软件系统的日益复杂&#xff0c;对日志管理的需求也日…...

农田自动化闸门的结构组成与功能解析

在现代化的农业节水灌溉领域中&#xff0c;农田自动化闸门的应用越来越广泛。它集成了先进的技术&#xff0c;通过自动化控制实现水资源的精准调度和高效利用。本文将围绕农田自动化闸门的结构组成&#xff0c;详细介绍其各个部件的功能和特点。 农田自动化闸门主要由闸门控制箱…...

Python解释器:CPython 解释器

一、什么是python解释器 Python解释器是一种用于执行Python代码的程序。 它将Python源代码转换为机器语言或字节码&#xff0c;从而使计算机能够执行。 1.1 Python解释器分类 1、CPython CPython 是 Python 的主要实现&#xff0c;由 C 语言编写。大多数用户在日常开发中使…...

layui 让table里的下拉框不被遮挡

记录&#xff1a;layui 让table里的下拉框不被遮挡 /* 这个是让table里的下拉框不被遮挡 */ .goods_table .layui-select-title,.goods_table .layui-select-title input{line-height: 28px;height: 28px; }.goods_table .layui-table-cell {overflow: visible !important; }.…...

专门的设计师服务平台/网站seo方案撰写

概述 Spring MVC框架的文件上传是基于commons-fileupload组件的文件上传。 因此所需要的包是commons-fileupload.jar和commons-io.jar包。 基于表单的文件上传 <form action"upload" method"post" enctype"multipart/form-data"><i…...

网站正在建设中的素材动图/百度在线识别图片

目录 题目 思路 考点 Code 题目 已知火星人使用的运算符为#、$,其与地球人的等价公式如下: x#y = 2*x+3*y+4 x$y = 3*x+y+2 1、其中x、y是无符号整数 2、地球人公式按C语言规则计算 3、火星人公式中,$的优先级高于#,相同的运算符,按从左到右的顺序计算 现有一段火星人…...

手机上可视化编程app/成都市seo网站公司

dLua类似gdb的lua调试器特性支持Linux平台C编写通过附加到其他进程上&#xff0c;进行调试gdb风格的调试指令&#xff0c;包括设置条件断点、查看变量、设置变量编译下载编译安装lua用脚本编译dlua&#xff0c;生成dlua与dluaagent.so&#xff0c;dlua是控制台&#xff0c;dlua…...

泉州专业网站建设哪家好/网站建设需要多少钱?

本发明涉及无线传感器网络领域&#xff0c;属于leach路由通信技术领域&#xff1a;。背景技术&#xff1a;&#xff1a;物联网技术飞速发展&#xff0c;无线传感器网络(wirelesssensornetworks&#xff0c;wsn)也逐渐成为互联网研究领域的热门话题&#xff0c;主要包含汇聚节点…...

主机wordpress/济南新站seo外包

推荐几个在线就能用的SQL 练习平台&#xff0c;你用过几个&#xff1f; 转载&#xff1a;https://www.toutiao.com/a6761788877918175757/?timestamp1574490925&appnews_article&group_id6761788877918175757&req_id20191123143515010023028159132CB7FA 转载理由…...

做果蔬零售的网站/深圳全网推广托管

1viewdidLoad在什么时候调用&#xff1a;viewDidLoad在代码运行到[self.view addSubview : x.view]时调用。...