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

4.Socket类、InetAddr类、Epoll类实现模块化

目录

1. InetAddr类

类定义

代码说明 

类实现

2.Socket类

类定义

类实现

3. Epoll类

类定义

构造与析构函数

方法实现

类实现

4. 使用模块化设计

示例使用(main.cpp)

5. 运行程序


随着程序复杂度的增加,单一的面向过程的代码会变得难以理解和维护。为了提高代码的可读性和可维护性,我们可以通过模块化的方式,将程序分解为多个类,每个类负责特定的功能。这种设计不仅提高了代码的复用率,还能帮助开发者集中精力在每个单独的功能模块上,便于维护和扩展。

在本文中,我们将介绍一种简单的模块化设计方法,使用C++面向对象的特性,来设计一个网络编程框架。我们将创建三个关键类:InetAddrSocketEpoll。这些类的设计目的在于简化网络编程的过程,提高代码的可读性和可维护性。

1. InetAddr类

InetAddr类主要负责处理与IP地址相关的操作。它封装了sockaddr_in结构体,并提供了一系列方法来获取IP地址和端口。

类定义

#pragma once // 确保该头文件只被包含一次  #include <string>     // 引入字符串类  
#include <arpa/inet.h> // 提供网络地址结构定义及函数  
#include <stdio.h>    // 标准输入输出库  class InetAddr {
public:// 默认构造函数  InetAddr();// 带参数的构造函数,接受端口和可选的IP地址  InetAddr(unsigned short port, const char* ip = nullptr);// 获取sockaddr_in结构的指针,供外部使用  const sockaddr_in* getAddr() const { return &addr_; }// 设置sockaddr_in结构的地址,供外部使用  void setAddr(const struct sockaddr_in& addr) { addr_ = addr; }// 将地址转换为IP字符串格式  std::string toIp() const;// 将地址转换为IP:端口格式的字符串  std::string toIpPort() const;// 获取端口号  unsigned short toPort() const;private:struct sockaddr_in addr_; // 存储网络地址信息的结构体  
};

代码说明 

  • InetAddr 类用于处理网络地址信息,主要封装了 sockaddr_in 结构体,提供了获取和设置网络地址、IP转换等操作。
  • 构造函数
    • 默认构造函数:初始化为0的地址,设置地址族为IPv4。
    • 带参数的构造函数:允许用户指定端口和IP地址,并适当地初始化 sockaddr_in 结构体。
  • 公共方法
    • getAddr():返回存储的地址信息的常量引用,便于外部访问。
    • setAddr():允许设置或修改当前存储的 sockaddr_in 地址。
    • toIp():转换当前地址为点分十进制格式的字符串。
    • toIpPort():将IP和端口组合为字符串,便于显示。
    • toPort():获取当前对象的端口号,返回值为无符号短整型。

Socket类负责封装与套接字相关的操作,包括创建、绑定、监听和接受连接等。

类实现

#include "InetAddr.h"         // 包含InetAddr类的定义  
#include <string.h>           // 包含字符串操作函数  
#include <arpa/inet.h>       // 包含网络地址转换函数  // 默认构造函数  
InetAddr::InetAddr() {// 将地址结构清零,确保没有未定义的值  memset(&addr_, 0, sizeof(addr_));
}// 带参数的构造函数,用于初始化port和ip  
InetAddr::InetAddr(unsigned short port, const char* ip) {// 将地址结构清零  memset(&addr_, 0, sizeof(addr_));addr_.sin_family = AF_INET; // 设置地址族为IPv4  addr_.sin_port = htons(port); // 将主机字节序的端口转换为网络字节序  // 如果未提供IP,则使用INADDR_ANY,允许接受任何IP地址的连接  if (ip == nullptr) {addr_.sin_addr.s_addr = htonl(INADDR_ANY);}else {// 将字符串形式的IP地址转换为网络字节序的二进制格式  inet_pton(AF_INET, ip, &addr_.sin_addr.s_addr);}
}// 将存储的IP地址转换为字符串格式  
std::string InetAddr::toIp() const {char ip[64] = { 0 }; // 存储转换后的IP地址  // 将网络字节序的IP地址转换为字符串形式  inet_ntop(AF_INET, &addr_.sin_addr.s_addr, ip, sizeof(ip));return ip; // 返回IP字符串  
}// 将IP地址和端口组合为 "IP:port" 的格式  
std::string InetAddr::toIpPort() const {char buf[128] = { 0 }; // 存储组合后的字符串  // 使用sprintf将IP和端口格式化为字符串  sprintf(buf, "%s:%d", toIp().c_str(), toPort());return buf; // 返回组合后的字符串  
}// 获取存储的端口号  
unsigned short InetAddr::toPort() const {// 将网络字节序的端口转换为主机字节序并返回  return ntohs(addr_.sin_port);
}

2.Socket类

类定义

#pragma once // 确保该头文件只被包含一次  class InetAddr; // 前向声明InetAddr类  class Socket
{
public:// 默认构造函数,初始化Socket对象  Socket();// 带参数的构造函数,使用给定的文件描述符初始化Socket  Socket(int fd);// 析构函数,关闭Socket以释放资源  ~Socket();// 将Socket绑定到指定的InetAddr地址  void bind(InetAddr* serv_addr);// 接受来自客户端的连接,并返回新的套接字文件描述符  int accept(InetAddr* addr);// 将Socket设置为监听状态,准备接受连接  void listen();// 设置Socket为非阻塞模式  void setNonblock();// 获取套接字文件描述符  int fd() const { return sockfd_; }private:int sockfd_; // 存储套接字的文件描述符  
};
  • 构造函数

    • Socket(): 默认构造函数,用于创建一个新的TCP套接字。
    • Socket(int fd): 通过传入的文件描述符初始化套接字对象,允许外部使用现有套接字。
  • 成员函数

    • void bind(InetAddr* serv_addr): 绑定给定的地址信息到套接字。
    • void listen(): 设置套接字为监听状态,准备接收连接请求。
    • int accept(InetAddr* peerAddr): 接受客户端连接,并返回新连接的套接字文件描述符,此外可以获取客户端地址。
    • int fd() const: 返回当前套接字的文件描述符,供外部访问。
  • 私有成员变量

    • const int sockfd_: 存储套接字的文件描述符,使用 const 限制其在对象生命周期内不可更改。

类实现

#include "Socket.h"                // 引入Socket类的定义  
#include "util.h"          
#include "InetAddr.h"              // 引入InetAddr类的定义  
#include <fcntl.h>                 // 提供fcntl函数的定义  
#include <unistd.h>                // 提供close函数的定义  // 默认构造函数,创建一个TCP套接字  
Socket::Socket(): sockfd_(socket(AF_INET, SOCK_STREAM, 0)) // 创建一个IPv4 TCP套接字  
{// 检查套接字创建是否成功,如果失败、打印错误信息  perror_if(sockfd_ == -1, "socket");
}// 带参数的构造函数,通过给定的文件描述符初始化套接字  
Socket::Socket(int fd): sockfd_(fd) // 使用提供的文件描述符进行初始化  
{// 检查文件描述符是否有效  perror_if(sockfd_ == -1, "socket(int fd)");
}// 析构函数,关闭套接字以释放资源  
Socket::~Socket()
{if (sockfd_ != -1) { // 确保套接字有效  close(sockfd_); // 关闭套接字文件描述符  sockfd_ = -1;   // 将文件描述符标记为无效,防止重复关闭  }
}// 将套接字绑定到指定的InetAddr地址  
void Socket::bind(InetAddr* serv_addr)
{// 调用系统级绑定函数  int ret = ::bind(sockfd_, (sockaddr*)serv_addr->getAddr(), sizeof(sockaddr_in));// 检查绑定是否成功,如果失败,打印错误信息  perror_if(ret == -1, "bind");
}// 接受客户端连接,并返回新的套接字文件描述符  
int Socket::accept(InetAddr* addr)
{struct sockaddr_in cliaddr; // 存储客户端地址信息  socklen_t len = sizeof(cliaddr); // 存储地址长度  // 调用系统级接受函数  int cfd = ::accept(sockfd_, (struct sockaddr*)&cliaddr, &len);// 检查接受客户端连接是否成功,如果失败,打印错误信息  perror_if(cfd == -1, "accept");// 设置已连接客户端的地址信息  addr->setAddr(cliaddr);// 输出新连接的客户端信息  printf("new client fd %d ip: %s, port: %d connected..\n", cfd, addr->toIp().c_str(), addr->toPort());return cfd; // 返回新连接的套接字文件描述符  
}// 将套接字设置为监听状态,准备接受连接  
void Socket::listen()
{// 调用系统级监听函数,最多同时处理128个连接请求  int ret = ::listen(sockfd_, 128);// 检查监听是否成功,如果失败,打印错误信息  perror_if(ret == -1, "listen");
}// 将套接字设置为非阻塞模式  
void Socket::setNonblock()
{// 获取当前文件描述符的标志  int flag = fcntl(sockfd_, F_GETFL);flag |= O_NONBLOCK; // 将非阻塞标志添加到当前标志中  // 将新的标志设置回文件描述符  fcntl(sockfd_, F_SETFL, flag);
}

3. Epoll类

Epoll类用于处理epoll事件,包括创建epoll实例、管理文件描述符添加/删除以及等待事件的发生。

类定义

#pragma once // 确保该头文件只被包含一次  #include <sys/epoll.h> // 包含epoll相关的系统调用  
#include <vector>      // 引入vector标准库  
using std::vector;    // 使用std命名空间中的vector类  class Epoll
{
public:// 构造函数,初始化epoll实例  Epoll();// 析构函数,清理epoll资源  ~Epoll();// 更新给定文件描述符的事件  void update(int sockfd, int events, int op);// 从epoll中删除指定的文件描述符  void epoll_delete(int fd);// 等待事件发生,返回活跃的文件描述符事件  void Epoll_wait(vector<epoll_event>& active, int timeout = 10);private:int epfd_;                       // epoll实例的文件描述符  struct epoll_event* events_;      // 存储返回的事件  
};

构造与析构函数

  • 创建epoll实例并初始化事件数组。
  • 在析构函数中释放资源。

方法实现

  • update(): 添加、修改或删除文件描述符的事件。
  • wait(): 使用epoll_wait()等待活动事件并填充事件数组。

类实现

#include "Epoll.h"               // 引入Epoll类的定义  
#include "util.h"                // 引入自定义工具函数头文件  
#include <string.h>              // 引入cstring库以使用memset和相关函数  
#include <unistd.h>             // 引入unistd.h以使用close函数const int SIZE = 1024;         // 定义epoll事件数组的大小  // 构造函数,创建一个新的epoll实例并初始化事件数组  
Epoll::Epoll(): epfd_(epoll_create(1)), // 创建epoll实例,参数为1,表示初始的事件数  events_(new epoll_event[SIZE]) // 动态分配事件数组  
{// 检查epoll_create是否成功,失败则调用perror_if输出错误信息  perror_if(epfd_ == -1, "epoll_create");// 初始化事件数组,清空内存  memset(events_, 0, sizeof(epoll_event) * SIZE);
}// 析构函数,清理epoll资源  
Epoll::~Epoll()
{// 删除事件数组  delete[] events_; // 释放动态分配的事件数组  // 将epfd_设为-1以避免重复关闭  if (epfd_ != -1) {close(epfd_); // 关闭epoll实例的文件描述符  epfd_ = -1; // 将文件描述符设置为-1表示无效  }
}// 更新给定的文件描述符,设置其事件类型  
void Epoll::update(int sockfd, int events, int op)
{struct epoll_event ev; // 创建epoll_event结构体以存储事件信息  memset(&ev, 0, sizeof(ev)); // 清空结构体  ev.data.fd = sockfd; // 将文件描述符存储在event结构体中  ev.events = events; // 设置感兴趣的事件  // 调用epoll_ctl更新epoll实例  int ret = epoll_ctl(epfd_, op, sockfd, &ev);// 检查epoll_ctl是否成功  perror_if(ret == -1, "epoll_ctl");
}// 从epoll中删除指定的文件描述符  
void Epoll::epoll_delete(int fd)
{// 调用epoll_ctl删除指定的文件描述符  int ret = epoll_ctl(epfd_, EPOLL_CTL_DEL, fd, nullptr);// 检查epoll_ctl是否成功  perror_if(ret == -1, "epoll_ctl del");
}// 等待事件发生,返回活跃的事件列表  
void Epoll::Epoll_wait(vector<epoll_event>& active, int timeout)
{// 调用epoll_wait等待事件的发生  int nums = epoll_wait(epfd_, events_, SIZE, timeout);// 检查epoll_wait是否成功  perror_if(nums == -1, "epoll_wait");// 将活跃的事件添加到active vector中  for (int i = 0; i < nums; ++i) {active.emplace_back(events_[i]); // 将每个活跃事件存入active数组  }
}

4. 使用模块化设计

通过将网络相关的功能分割成几个类,可以简化主要的服务器逻辑。使用这些类,我们可以方便地进行网络编程而不必关注底层的细节。

示例使用(main.cpp)

下面是如何使用这些类来构建一个简单的服务器:

#include "Epoll.h"        // 引入Epoll类的定义  
#include "Socket.h"      // 引入Socket类的定义  
#include "util.h"          // 引入工具函数的头文件  
#include "InetAddr.h"       // 引入InetAddr类的定义  
#include <stdio.h>              // 引入标准输入输出库  
#include <string.h>             // 引入cstring库以使用memset和相关函数  
#include <unistd.h>             // 引入unistd库以使用read和close函数  const int READ_BUFFER = 1024;  // 定义读取缓冲区的大小  
const int MAXSIZE = 1024;      // 定义最大连接数(未使用)  // 前向声明函数,用于处理事件  
void handleEvent(int sockfd, Epoll& poll);int main()
{Socket serv_socket;             // 创建一个服务器套接字  InetAddr saddr(10000);         // 创建一个InetAddr对象,用于绑定到端口10000  serv_socket.bind(&saddr);       // 绑定服务器套接字到指定地址  serv_socket.listen();           // 开始监听客户端连接  serv_socket.setNonblock();      // 设置服务器套接字为非阻塞模式  Epoll poll;                     // 创建epoll实例  poll.update(serv_socket.fd(), EPOLLIN, EPOLL_CTL_ADD); // 将服务器套接字添加到epoll实例中,监控可读事件  // 主循环,持续处理事件  while (1){vector<epoll_event> active; // 存储活动事件的向量  poll.Epoll_wait(active);     // 等待事件的发生  int nums = active.size();    // 当前活动事件的数量  for (int i = 0; i < nums; ++i) {int curfd = active[i].data.fd; // 获取当前事件对应的文件描述符  // 检查是否是可读事件  if (active[i].events & EPOLLIN) {if (curfd == serv_socket.fd()) { // 如果当前文件描述符是服务器套接字  InetAddr caddr;              // 创建一个InetAddr对象,存储客户端地址  Socket* cli_socket = new Socket(serv_socket.accept(&caddr)); // 接受客户端连接并创建新的套接字  // 注意:需要处理内存泄漏(后续版本将修复内存管理)  cli_socket->setNonblock();   // 设置客户端套接字为非阻塞模式  poll.update(cli_socket->fd(), EPOLLIN, EPOLL_CTL_ADD); // 将客户端套接字添加到epoll实例  }else {handleEvent(curfd, poll);   // 处理其他可读事件  }}else if (active[i].events & EPOLLOUT) {// 其他事件以后的版本会实现  }}}return 0; // 主程序结束  
}// 处理可读事件的函数  
void handleEvent(int sockfd, Epoll& poll) {char buf[READ_BUFFER];         // 声明读取缓冲区  memset(buf, 0, sizeof(buf));   // 清空缓冲区  // 从套接字读取数据  ssize_t bytes_read = read(sockfd, buf, sizeof(buf));// 判断读取结果  if (bytes_read > 0) {// 成功读取数据,输出客户端发来的消息  printf("client fd %d says: %s\n", sockfd, buf);// 将接收到的数据写回给客户端(回显)  write(sockfd, buf, bytes_read);}else if (bytes_read == -1) { // 读取出错  perror_if(1, "read");    // 调用错误处理函数  }else if (bytes_read == 0) {  // 客户端断开连接  printf("client fd %d disconnected\n", sockfd);poll.epoll_delete(sockfd); // 从epoll实例中删除该套接字  close(sockfd);             // 关闭套接字  }
}

5. 运行程序

g++ -o Server main.cpp Epoll.cpp util.cpp Socket.cpp InetAddr.cpp

编译完成后,可以通过以下命令运行服务器:

./Server        # 启动服务器

客户端可以使用之前的客户端程序作为连接方式,确保与服务器在同一网络下运行。

相关文章:

4.Socket类、InetAddr类、Epoll类实现模块化

目录 1. InetAddr类 类定义 代码说明 类实现 2.Socket类 类定义 类实现 3. Epoll类 类定义 构造与析构函数 方法实现 类实现 4. 使用模块化设计 示例使用&#xff08;main.cpp) 5. 运行程序 随着程序复杂度的增加&#xff0c;单一的面向过程的代码会变得难以理…...

19 python 模块

在办公室的日常工作中&#xff0c;我们常常会用到各种各样的工具&#xff0c;像计算器用于计算数据、打印机用来打印文件、订书机将纸张装订成册等。这些工具会被反复使用&#xff0c;而且不同的工具具有不同的功能。 一、模块的定义 在 Python 里&#xff0c;模块就如同一个…...

医疗智能体通信整合-大模型训练中沟通优化策略研究

一、引言:医疗模型训练的沟通困境 1.1 医疗 AI 发展背景 在数智化浪潮的推动下,医疗 AI 正以前所未有的速度融入现代医疗体系。从智能影像诊断助力医生精准识别病灶,到基于大数据分析的个性化药物研发,医疗 AI 在提升医疗效率、改善医疗质量方面展现出巨大潜力。据相关数据…...

LearnOpenGL-笔记-其六

今天我们来聊一些更深入的东西&#xff1a; Depth Testing 在之前的学习过程中&#xff0c;我们有接触过深度缓冲&#xff0c;彼时的深度缓冲的意义就是可以让我们体现出深度的差异从而达到立体的效果&#xff0c;而现在我们将在深度缓冲的基础进一步扩展&#xff0c;进行深度…...

【商城实战(91)】安全审计与日志管理:为电商平台筑牢安全防线

【商城实战】专栏重磅来袭&#xff01;这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建&#xff0c;运用 uniapp、Element Plus、SpringBoot 搭建商城框架&#xff0c;到用户、商品、订单等核心模块开发&#xff0c;再到性能优化、安全加固、多端适配&#xf…...

Windows 10更新失败解决方法

在我们使用 Windows 时的时候&#xff0c;很多时候遇到系统更新 重启之后却一直提示“我们无法完成更新&#xff0c;正在撤销更改” 这种情况非常烦人&#xff0c;但其实可以通过修改文件的方法解决&#xff0c;并且正常更新到最新版操作系统 01修改注册表 管理员身份运行注…...

【安当产品应用案例100集】042-基于安当KADP实现机密文件安全流转

一、客户需求 某集团公司客户&#xff0c;在系统业务流中&#xff0c;存在大量的内部文件流转的需求。内部业务文件有不同的安全密级&#xff0c;最初在文件流转时&#xff0c;公司内部规定点对点的文件传输&#xff0c;要使用加密工具加密后再发给需要的一方。这种方式虽然能…...

【网络】Socket套接字

目录 一、端口号 二、初识TCP/UDP协议 三、网络字节序 3.1 概念 3.2 常用API 四、Socket套接字 4.1 概念 4.2 常用API &#xff08;1&#xff09;socket &#xff08;2&#xff09;bind sockaddr结构 &#xff08;3&#xff09;listen &#xff08;4&#xff09;a…...

蓝桥杯[每日一题] 真题:连连看

题目描述 小蓝正在和朋友们玩一种新的连连看游戏。在一个 n m 的矩形网格中&#xff0c;每个格子中都有一个整数&#xff0c;第 i 行第 j 列上的整数为 Ai, j 。玩家需要在这个网格中寻找一对格子 (a, b) − (c, d) 使得这两个格子中的整数 Aa,b 和 Ac,d 相等&#xff0c;且它…...

新手SEO优化实战快速入门

内容概要 对于SEO新手而言&#xff0c;系统化掌握基础逻辑与实操路径是快速入门的关键。本指南以站内优化为切入点&#xff0c;从网站结构、URL设计到内链布局&#xff0c;逐层拆解搜索引擎友好的技术框架&#xff1b;同时聚焦关键词挖掘与内容策略&#xff0c;结合工具使用与…...

Android面试总结之Glide源码级理解

当你的图片列表在低端机上白屏3秒、高端机因内存浪费导致FPS腰斩时&#xff0c;根源往往藏在Glide的内存分配僵化、磁盘混存、网络加载无优先级三大致命缺陷中。 本文从阿里P8级缓存改造方案出发&#xff0c;结合Glide源码实现动态内存扩容、磁盘冷热分区、智能预加载等黑科技&…...

基于类型属性的重载

算法重载 在一个泛型算法中引入更为特化的变体&#xff0c;这种设计和优化方式称为算法特化。之所以需要算法特化&#xff0c;原因有二&#xff1a; 针对特定类型使用更加合理的实现&#xff0c;对于const char *&#xff0c;less的第二个实现更加合理 template <typename…...

对称加密算法和非对称加密算法

在这个互联网普及的时代&#xff0c;在不同终端对敏感甚至机密数据进行传输是非常常见的场景&#xff0c;但是如何保证数据传输过程的安全性和高效性是一个值得深入探讨的问题。 为此&#xff0c;伟大的人类研究出了多种加密算法&#xff0c;我们可以大致将其分为两类&#xf…...

工程数字建造管理系统平台有哪些?好的数字建造管理系统推荐

一、什么是工程数字建造管理系统平台&#xff1f; 工程数字建造管理系统平台是一种集成了先进信息技术&#xff08;如云计算、大数据、物联网等&#xff09;的综合性管理工具&#xff0c;它旨在通过数字化手段提升工程建造全过程的管理效率和决策水平。这一平台不仅覆盖了工程…...

CMake ERROR: arm-none-eabi-gcc is not able to compile a simple test program.

用 cmake 构建 STM32 工程问题【已解决】 环境信息 os: ubuntu22.04gcc: arm-none-eabi-gcc (Arm GNU Toolchain 13.2.rel1 (Build arm-13.7)) 13.2.1 20231009cmake: cmake version 3.22.1ninja: 1.10.1 问题 log [main] 正在配置项目: Olidy [driver] 删除 /home/pomegr…...

容器主机CPU使用率突增问题一则

关键词 LINUX、文件系统crontab 、mlocate根目录使用率 There are many things that can not be broken&#xff01; 如果觉得本文对你有帮助&#xff0c;欢迎点赞、收藏、评论&#xff01; 一、问题现象 业务一台容器服务器&#xff0c;近期经常收到cpu不定期抖动告警&#x…...

CTFshow【命令执行】web29-web40 做题笔记

web29----过滤关键字 正则匹配&#xff0c;过滤flag&#xff0c;可以使用通配符绕过 先查看目录 使用通配符&#xff1f;查看flag 点击查看源代码 web30---过滤函数和关键字 看到过滤了system执行系统命令和flag&#xff0c;php关键字 找一个与其功能差不多的执行函数passthr…...

L2正则化:优化模型的平滑之道

常见的正则化方法1. **L1正则化&#xff08;Lasso&#xff09;**1.1基本原理1.2特点1.3数学推导1.4参数更新1.5选择合适的正则化系数1.6优点1.7缺点1.8实际应用中的注意事项1.9示例 2. **L2正则化&#xff08;Ridge&#xff09;**L2正则化的定义L2正则化如何防止过拟合1. **限制…...

Golang 的 GMP 调度机制常见问题及解答

文章目录 Golang GMP 调度模型详解常见问题基础概念1. GMP 各组件的作用是什么&#xff1f;2. 为什么 Go 需要自己的调度器&#xff1f;3. GOMAXPROCS 的作用是什么&#xff1f; 调度流程4. Goroutine 如何被调度到 M 上执行&#xff1f;5. 系统调用会阻塞整个线程吗&#xff1…...

使用VSCODE导致CPU占用率过高的处理方法

1&#xff1a;cpptools 原因&#xff1a;原因是C/C会在全局搜索文件&#xff0c;可以快速进行跳转&#xff1b;当打开的文件过大&#xff0c;全局搜索文件会占用大量CPU&#xff1b; 处理方法&#xff1a; 1&#xff1a;每次只打开小文件夹&#xff1b; 2&#xff1a;打开大文…...

17--华为防火墙智能选路全解:网络世界的智能导航系统

华为防火墙智能选路全解&#xff1a;网络世界的智能导航系统 开篇故事&#xff1a;快递小哥的烦恼与网络世界的相似性 想象你是个快递站站长&#xff0c;每天要处理来自全国各地的包裹。突然某天遇到&#xff1a; &#x1f69a; 双11爆仓&#xff1a;如何把包裹最快送到客户手…...

CSS-BFC(块级格式化上下文)

一、BFC 的本质理解&#xff08;快递仓库比喻&#xff09; 想象一个快递分拣仓库&#xff08;BFC容器&#xff09;&#xff0c;这个仓库有特殊的规则&#xff1a; 仓库内的包裹&#xff08;内部元素&#xff09;摆放不影响其他仓库包裹必须整齐堆叠&#xff0c;不能越界不同仓…...

Java 大视界 -- Java 大数据在智慧港口集装箱调度与物流效率提升中的应用创新(159)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...

ZygoPlanner:一种基于图形的三阶段框架,用于颧骨种植体植入的最佳术前规划|文献速递-医学影像人工智能进展

Title 题目 ZygoPlanner: A three-stage graphics-based framework for optimal preoperative planning of zygomatic implant placement ZygoPlanner&#xff1a;一种基于图形的三阶段框架&#xff0c;用于颧骨种植体植入的最佳术前规划 01 文献速递介绍 1.1 研究背景 颧…...

【2.项目管理】2.4 Gannt图【甘特图】

甘特图&#xff08;Gantt&#xff09;深度解析与实践指南 &#x1f4ca; 一、甘特图基础模板 项目进度表示例 工作编号工作名称持续时间(月)项目进度&#xff08;周&#xff09;1需求分析3▓▓▓░░░░░░░2设计建模3░▓▓▓░░░░░░3编码开发3.5░░░▓▓▓▓░░…...

python学习笔记(1)

为什么要学python 目前在研究网站的搭建,想通过python搭建一个我的世界资源买卖的平台,然后就开始研究python了,其实这不是我第一次研究python了,之前学的都不咋样,现在温故而知新,好好研究一下python。 Python的变量 在此之前先简单的介绍一下变量,给第一次接触的小…...

刚刚整理实测可用的股票数据API接口集合推荐:同花顺、雅虎API、智兔数服、聚合数据等Python量化分析各项数据全面丰富

在金融科技高速发展的今天&#xff0c;股票API接口已成为开发者、量化交易者和金融从业者的核心工具之一。它通过标准化的数据接口&#xff0c;帮助用户快速获取实时或历史市场数据&#xff0c;为投资决策、策略回测和金融应用开发提供支持。本文将深入解析股票API的核心功能、…...

2025 年吉林省燃气企业从业人员考试:实用备考攻略与考试提分要点​

2025 年吉林省燃气企业从业人员考试报名通过吉林燃气行业管理系统。报名资料包含企业的环保达标证明&#xff08;燃气行业涉及环保要求&#xff09;、个人的岗位任职证明等。实用备考攻略是&#xff0c;关注吉林在燃气分布式能源系统建设方面的进展&#xff0c;结合《燃气冷热电…...

dubbo http流量接入dubbo后端服务

简介 dubbo协议是基于TCP的二进制私有协议&#xff0c;更适合作为后端微服务间的高效RPC通信协议&#xff0c;也导致dubbo协议对于前端流量接入不是很友好。在dubo框架中&#xff0c;有两种方式可以解决这个问题&#xff1a; 多协议发布【推荐】&#xff0c;为dubbo协议服务暴…...

自动驾驶04:点云预处理03

点云组帧 感知算法人员在完成点云的运动畸变补偿后&#xff0c;会发现一个问题&#xff1a;激光雷达发送的点云数据包中的点云数量其实非常少&#xff0c;完全无法用来进行后续感知和定位层面的处理工作。 此时&#xff0c;感知算法人员就需要对这些数据包进行点云组帧的处理…...

小程序中过滤苹果设备中的表情(即 emoji)

在小程序中过滤苹果设备中的表情&#xff08;即 emoji&#xff09;&#xff0c;通常需要考虑以下几个方面&#xff1a;识别 emoji、处理用户输入、以及在显示或存储时进行过滤。以下是具体的实现思路和步骤&#xff1a; 1. 理解苹果中的表情&#xff08;Emoji&#xff09; 苹果…...

软件性能测试中的“假阳性”陷阱

软件性能测试中的“假阳性”陷阱主要表现为错误警报频繁、资源浪费严重、测试可信度降低。其中&#xff0c;错误警报频繁是最常见且最严重的问题之一&#xff0c;“假阳性”现象会导致开发团队在解决不存在的问题上花费大量时间。据行业调查显示&#xff0c;超过30%的性能优化成…...

现代优雅品牌杂志包装徽标设计衬线英文字体安装包 Relish – Aesthetic Font

CS Relish – 美学字体&#xff1a;优雅与现代简约的结合 永恒的现代 Serif 字体 CS Relish 是一种现代衬线字体&#xff0c;将极简主义美学与精致精致融为一体。凭借其时尚、干净的字体和平衡的结构&#xff0c;它给人一种优雅和现代的印象。这款字体专为那些欣赏微妙和优雅的…...

《Oracle服务进程精准管控指南:23c/11g双版本内存优化实战》 ——附自动化脚本开发全攻略

正在学习或者是使用 Oracle 数据库的小伙伴&#xff0c;是不是对于那个一直启动且及其占用内存的后台进程感到烦躁呢&#xff1f;而且即使是手动去开关也显得即为麻烦&#xff0c;所以基于我之前所学习到的方法&#xff0c;我在此重新整理&#xff0c;让大家动动手指就能完成开…...

《寒门枭雄传》章回目录与核心故事设计(36回)

《寒门枭雄传》章回目录与核心故事设计&#xff08;36回&#xff09; 主线&#xff1a;寒门崛起→权力异化→制度轮回 核心冲突&#xff1a;个人奋斗 vs 制度性压迫 第一卷京口草鞋摊的野望&#xff08;第1-12回&#xff09; 主题&#xff1a;寒门之困始于生存&#xff0c;终…...

C语言学习笔记(抱佛脚版)

毕业一年&#xff0c;发现记性是真的差&#xff0c;每次想起之前的知识总是想不全&#xff0c;看别人写的资料也懵懵懂懂。于是我索性自己再学一遍&#xff0c;并且记录一下。希望对你们也有所帮助。 正片开始&#xff01; 前面的什么if for都不难理解&#xff0c;嵌套的话也…...

DeepSeek-V3-0324 模型发布:开源 AI 性能再攀高峰,推理与编码能力逼近顶级闭源模型

2025 年 3 月 24 日&#xff0c;国内 AI 公司深度求索&#xff08;DeepSeek&#xff09;悄然推出 V3 模型的升级版本 DeepSeek-V3-0324。尽管此次更新并非市场期待的 V4 或 R2 版本&#xff0c;但其在推理速度、编码能力、数学推理及开源生态上的突破&#xff0c;仍迅速引发全球…...

清晰易懂的Cursor实现AI编程从安装到实战TodoList开发

一、Cursor简介与安装部署 什么是Cursor&#xff1f; Cursor是一款基于AI的智能代码编辑器&#xff0c;它集成了强大的AI编程助手功能&#xff0c;能够通过自然语言交互帮助开发者生成、优化和调试代码。与传统的代码编辑器不同&#xff0c;Cursor可以理解你的编程意图&#…...

(二) 深入了解AVFoundation - 播放:AVFoundation 播放基础入门

引言 AVFoundation 是 Apple 提供的强大多媒体框架&#xff0c;支持音视频播放、录制、处理等功能。在 iOS 开发中&#xff0c;AVFoundation 是实现视频播放的核心技术之一。 本篇文章将简单介绍如何使用 AVPlayer、AVPlayerItem 和 AVPlayerLayer 进行视频播放&#xff0c;并…...

重磅推出稳联技术Profinet转CANopen网关智能工厂解决方案!

重磅推出稳联技术Profinet转CANopen网关智能工厂解决方案&#xff01; 稳联技术Profinet转CANopen网关应运而生——它如同一座智能桥梁☺&#xff0c;打通两大主流工业协议&#xff0c;让异构网络无缝互联&#xff0c;助您释放设备潜力&#xff0c;实现真正的“万物互联”&…...

【问题解决】Linux安装conda修改~/.bashrc配置文件后,root 用户下显示 -bash-4.2#

问题描述 在Linux安装conda下的python环境时候&#xff0c;修改了~/.bashrc文件&#xff0c;修改完成后&#xff0c;再次进入服务器后&#xff0c;登录时候显示的不是正常的[rootlocalhost ~]#&#xff0c;而是-bash-4.2# 原因分析&#xff1a; 网上原因有&#xff1a;/root下…...

关于deepseek

DeepSeek&#xff1a;领先的人工智能研究与创新公司 公司简介 DeepSeek&#xff08;深度求索&#xff09;是一家专注于人工智能&#xff08;AI&#xff09;技术研发的创新公司&#xff0c;致力于推动大模型、自然语言处理&#xff08;NLP&#xff09;、机器学习&#xff08;M…...

EtherCAT转ProfiNet协议转换网关构建西门子PLC与海克斯康机器人的冗余通信链路

一、案例背景 某电子制造企业的5G通信模块组装线&#xff0c;采用西门子S7-1200PLC&#xff08;ProfiNet主站&#xff09;进行产线调度&#xff0c;而精密组装工序由3台海克斯康工业机器人&#xff08;EtherCAT从站&#xff09;完成。由于协议差异&#xff0c;机器人动作与PLC…...

李宏毅机器学习笔记(1)—机器学习基本概念+深度学习基本概念

机器学习基本概念 1、获取模型 步骤 1.1、假定未知函数 带未知参数的函数 1.2、定义损失函数 真实值&#xff1a;label MAE MSE 几率分布&#xff0c;cross-entropy? 1.3、优化 单独考虑一个参数 让损失函数最小&#xff0c;找导数为零的点 单独考虑w&#xff0c;w…...

RAG生成中的多文档动态融合及去重加权策略探讨

目录 RAG生成中的多文档动态融合及去重加权策略探讨 一、RAG生成概述 二、多文档动态融合策略 1. 拼接与分段编码 2. 独立编码与后续融合 3. 基于查询的动态加权 三、检索结果的去重与加权策略 1. 去重策略 2. 加权策略 四、实践中的挑战与思考 五、结语 RAG生成中的…...

对匿名认证的理解

概述&#xff1a;在 Spring Security 中&#xff0c;** 匿名认证&#xff08;Anonymous Authentication&#xff09;** 是一种特殊的认证机制&#xff0c;用于处理未提供有效凭证的请求。 匿名认证的本质 目的&#xff1a;允许未认证用户访问特定资源。原理&#xff1a; 当请求…...

leetcoed0044. 通配符匹配 hard

1 题目&#xff1a;通配符匹配 官方难度&#xff1a;难 给你一个输入字符串 (s) 和一个字符模式 ( p ) &#xff0c;请你实现一个支持 ‘?’ 和 ‘*’ 匹配规则的通配符匹配&#xff1a; ‘?’ 可以匹配任何单个字符。 ‘*’ 可以匹配任意字符序列&#xff08;包括空字符序…...

航拍数据集汇总,覆盖车辆/船舶检测/物体评估/城市景观……

随着无人机的普及化和计算机视觉技术的迅猛发展&#xff0c;无人机航拍作为一种创新的摄影方式&#xff0c;正以前所未有的速度走进大众视野。它打破了传统拍摄的局限&#xff0c;为我们开启了「上帝视角」。航拍硬件性能逐渐逼近物理极限&#xff0c;算法优化的难度也日益增大…...

【SECS】初识SECS协议

【SECS】初识SECS协议 基本知识流和功能函数数量官方文件中缩写标注正常是不是都是主机向设备端?对数据信息中第1字节第1-2位官网介绍 S1F1双向指令说明测试H发起端E发起端 参考资料 基本知识 SECS&#xff08;SEMI Equipment Communications Standard&#xff09;即半导体设…...

RL基础以及AlphaGo、AlphaGo Zero原理

RL基础 Q价值函数和状态价值函数 Action-Value function&#xff1a; Q ( s , a ) Q(s, a) Q(s,a)是agent在状态s下执行某一个动作&#xff08;如向上走&#xff09;&#xff0c;所获得的及时奖励和未来折扣的累计奖励 State-Value function&#xff1a; V ( s ) V(s) V(s)是…...