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

C++学习之外联接口-项目总结

目录

1.知识点概述

2.秘钥协商的秘钥写入到共享内存中

3.秘钥写共享内存测试

4.外联接口作用

5.外联接口类的封装

6.配置文件定义

7.外联接口的打包

8.外联接口的实现

9.外联接口读共享内存得到秘钥

10.将外联接口制作成动态库

11.外联接口的使用

12.外联接口测试-有bug

13.外联接口测试

14.外联接口的改进

15.知识点总结

16.项目中知识点总结

17.线程池思想

18.ora-24550解决方案

19.秘钥注销和校验


1.知识点概述

> 为了更容易(同时也更安全的管)的使用动态内存,新的标准库(C++11)提供了两种智能指针(smart pointer)类型来管理动态对象。智能指针的行为类似于常规指针。重要的区别是它负责自动释放所指向的对象。新标准提供的这两种智能指针的区别在于管理底层指针的方式:shared_ptr允许多个指针指向同一个对象;unique_ptr则独占所指向的对象。
>
> week_ptr -> 管理shared_ptr
>
> auto_ptr  -> c++17
>
> **智能指针也是模板。**

- 头文件

  ```c++
  #include <memory>
  ```

- 一般格式

  ```c
  shared_ptr<string> p1;  //指向string的shared_ptr
  shared_ptr<int> p2;       //指向int的shared_ptr

2.秘钥协商的秘钥写入到共享内存中

```c
int * a = new int(100);
// 使用智能指针和一块内存进行管联, 这块内存就有一个引用计数, 关联一次引用计数+1
// 当内存引用计数减为 0 时候, 内存就被指针指针删除了
```



> **shared_ptr 允许有多个指针指向同一个对象**, **我们可以认为每个share_ptr都有一个关联的计数器,通常称为引用计数(reference count)。无论何时我们拷贝一个shared_ptr,计数器都会递增。**<font color="red">一旦某个对象的引用计数变为0,这个对象会被自动删除。</font>
>
> 例如这些都会使所关联的计数器**递增**:
>
> **(1)当用一个shared_ptr初始化另外一个shared_ptr**
>
> **(2)将它作为参数传递给另外一个函数**
>
> **(3)作为函数的返回值**

3.秘钥写共享内存测试

> 例如这些操作会使计数器都会**递减:**
>
> **(1)给share_ptr赋新的值**
>
> **(2)share_ptr被销毁**
>
> **(3)局部的share_ptr离开作用域**

- 初始化

  ```c
  // 通过 shared_ptr 的构造函数,可以让 shared_ptr 对象托管一个 new 运算符返回的指针
  shared_ptr<T> ptr(new T);  // T 可以是 int、char、类等各种类型
  // 使用make_shared函数分配一个对象并初始化它,make_shared函数返回一个指向此对象的shared_ptr
  template< class T, class... Args >
  shared_ptr<T> make_shared( Args&&... args );
  // 通过另一个智能指针初始化
  shared_ptr<T> ptr = ptr1;
  shared_ptr<T> ptr(ptr1);

4.外联接口作用

 查看引用计数

  ```c++
  long use_count() const noexcept;
  ```

- 返回存储的指针

  ```c++
  T* get() const noexcept;
  ```

- 重置管理的指针

  ```c++
  void reset( Y* ptr );
  ```

5.外联接口类的封装

- 删除器 -> 回调函数 -> 删除智能指针管理的内存

  ```c
  // 默认, 删除器函数, 会自动调用
  default_delete()
  shared_ptr<int> ptr(new int(2), default_delete<int>());
  // share_ptr 的 默认删除器, 不能删除new的数组内存, 需要自己指定删除器函数
  // 通过share_ptr的构造函数, 在构造函数的第二个参数的位置上, 指定回调函数
  // 匿名函数
  [](args)
  {
  }

6.配置文件定义

    shared_ptr<int> ptr1(new int[10], [](int *array) {
          delete[]array;
      });
      shared_ptr<A> ptr2(new A[10], [](A* a) {
          delete []a;
      });
  // 规律:
  删除器函数需要一个参数, 参数类型: 智能指针管理的内存地址的类型, 函数体中进行内存释放
  删除器函数别智能指针调用的时候, 会将new得到的内存地址, 传递给删除器函数的参数
  ```

7.外联接口的打包

> **unique_ptr独占所指向的对象。**同一时刻只能有一个 unique_ptr 指向给定对象(通过禁止拷贝语义, 只有移动语义来实现)

- 初始化

  ```c
  // 使用构造函数
  unique_ptr<T> ptr(new T);  // T 可以是 int、char、类等各种类型
  // 使用make_unique
  template< class T, class... Args >
  unique_ptr<T> make_unique( Args&&... args );
  ```

- unique_ptr 支持对数组内存管理

8.外联接口的实现

# 2. 外联接口

1. 接口类的封装

   ```c++
   // 读共享内存中的秘钥, 进行对称加密
   // des , 3des , aes
   class MyInterface
   {
   public:
       // json参数磁盘的json格式的配置文件
       MyInterface(string json);
       ~MyInterface();
       // 数据加密
       // 参数: 待加密的数据->明文, 返回值: 密文
       string encryptData_des(string str);
       string encryptData_3des(string str);
       string encryptData_aes(string str);
       // 数据解密
       // 参数: 待解密的数据-密文, 返回值: 明文
       string decryptData_des(string str);
       string decryptData_3des(string str);
       string decryptData_aes(string str);
   }

9.外联接口读共享内存得到秘钥

10.将外联接口制作成动态库

2. 提供的接口不是一个应用程序 -> 不是进程

   - 如果从共享内存中读数据?
     - 虽然接口不是程序, 但是要被业务程序调用
       - 业务程序是进程
         - 通过业务程序完成进程间通信
   - 外联接口要求必须要通用
     - 必须用通过配置文件读配置信息 -> 找到共享内存

11.外联接口的使用

3. json格式配置文件的定义

   ```json
   // 共享内存中存储的节点结构
   class NodeSecKeyInfo
   {
   public:
       NodeSecKeyInfo() : status(0), seckeyID(0)
       {
           bzero(clientID, sizeof(clientID));
           bzero(serverID, sizeof(serverID));
           bzero(seckey, sizeof(seckey));
       }
       int status;        // 秘钥状态: 1可用, 0:不可用
       int seckeyID;    // 秘钥的编号
       char clientID[12];    // 客户端ID, 客户端的标识
       char serverID[12];    // 服务器ID, 服务器标识
       char seckey[128];    // 对称加密的秘钥
   };

12.外联接口测试-有bug

   ```json
   // 服务器端, 必须能找到对应的秘钥
   {
       "ShmKey":"/usr/lib",    // 通过 shmKey 打开一块已经存在的共享内存
       "MaxNode":100,            // 共享内存中存储的最大节点数 -> 用于遍历
       "ServerID":"999",        // 当前秘钥协商服务器的ID
       "ClientID":"666"        // 和当前业务服务器通信的客户端ID --> 这个是动态的
   }
   
   // 客户端
   {
       "shmKey":"/usr/local",    // 通过 shmKey 打开一块已经存在的共享内存
       "MaxNode":1,            // 共享内存中存储的最大节点数 -> 用于遍历
       "ServerID":"999",
       "ClientID":"666"
   }

13.外联接口测试

 ```json
   // 改进配置文件
   // 将配置文件中的serverID和clientID去掉
   // 找秘钥的方式:
       - 通过clientID和serverID进行查找
       - 通过秘钥ID查找
   
   // 通过配置文件打开共享内存
   {
       "shmKey":"/usr/local",    // 通过 shmKey 打开一块已经存在的共享内存
       "MaxNode":1,            // 共享内存中存储的最大节点数 -> 用于遍历
   }
   

14.外联接口的改进

 ```c++
   // 共享内存类修改
   class SecKeyShm : public BaseShm
   {
   public:
       // 打开或创建一块共享内存
       // 这个操作是在父类中做的
       SecKeyShm(int key, int maxNode);
       SecKeyShm(string pathName, int maxNode);
       ~SecKeyShm();
   
       void shmInit();
       int shmWrite(NodeSecKeyInfo* pNodeInfo);
       NodeSecKeyInfo shmRead(string clientID, string serverID);
       NodeSecKeyInfo shmRead(int keyID);
       // 通过这个函数读共享内存中的第一个NodeSecKeyInfo
       // 给客户端使用
       NodeSecKeyInfo shmFirstNode();
   
   private:
       int m_maxNode;
   };
   ```

15.知识点总结

4. 如何给用户使用?

   - 将接口打包成库(静态/动态)

     - 静态库

       ```c
       // 生成.o
       gcc/g++ *.c/*.cpp -c
       // 打包.o
       ar rcs libxxx.a  *.o
       ```

     - 动态库

       ```shell
       # 生成.o -> 和位置无关使用的是相对地址
       gcc/g++ *.c/*.cpp -c -fpic
       # 生成动态库
       gcc/g++ -shared *.o -o libxxx.so
       ```

16.项目中知识点总结

 - 发布对应的头文件即可



# 3.其他操作

## 3.1 OCCI - ORA-24550

在使用occi多线程访问oralce服务器的时候, 会出现ORA-24550 错误, 错误信息如下: 

```shell
ORA-24550 : signal received : [si_signo=11] [si_errno=0] [si_code=50] [si_adr =
2020202020202020] killed

17.线程池思想

18.ora-24550解决方案

该错误会导致进程终止, 修改方案如下:

1. 使用find命令所有oracle服务器端的 `sqlnet.ora` 文件, 在文件中添加下配置项: 

   ```shell
   DIAG_ADR_ENABLED=OFF
   DIAG_SIGHANDLER_ENABLED=FALSE
   DIAG_DDE_ENABLED=FALSE
   ```

2. 如果该问题还未解决, 在调用 `OCCI` 接口的客户端对应oracle目录中, 例如, 我的客户端对用的oralce目录为
   `/opt/instantclient_11_2` , 在该目录下的 `network/admin` 中添加文件 `sqlnet.ora` , 内容如下: 

   ```shell
   SQLNET.AUTHENTICATION_SERVICES= (NTS)
   NAMES.DIRECTORY_PATH= (TNSNAMES,HOSTNAME)
   DIAG_ADR_ENABLED=OFF
   DIAG_SIGHANDLER_ENABLED=FALSE
   DIAG_DDE_ENABLED=FALSE

19.秘钥注销和校验

## 3.2 秘钥校验

对比通信双方使用的秘钥是否相同

- 如何比较?
  - 在客户端将秘钥进行哈希计算 -> 哈希值
  - 将哈希值发送给服务器
  - 服务器端也将秘钥生成哈希值
  - 两个哈希值进行对比即可

## 3.3 秘钥注销

- 现有的共享内存中的秘钥不用了, 标记为不可用
  - 客户端:
    - 将本地共享内存中的秘钥状态进行修改
    - 通知服务器这个秘钥不用了
    - 将这个秘钥的ID发送给服务器
  - 服务器端:
    - 通过秘钥的ID找到共享内存中的秘钥, 标记为不可用
    - 更新数据库中这个秘钥的状态

相关文章:

  • sqlmap使用tamper解决过滤waf问题 实战解决[极客大挑战 2019]BabySQL 1
  • 第十九讲 | XGBoost 与集成学习:精准高效的地学建模新范式
  • daz dForce to UE 的原理分析
  • 网络6 配置静态地址 路由表
  • RAG(检索增强生成)学习路径全解析:从入门到精通
  • 【AI提示词】网络安全专家
  • 神经子图同构计数
  • 如何通过自动化解决方案提升企业运营效率?
  • 鸿蒙开发-页面跳转
  • linux命令之tee(Linux Command Tee)
  • Javaweb后端 maven高级 maven聚合
  • GESP2023年12月认证C++七级( 第二部分判断题(1-5))
  • Named Entity Recognition with Bidirectional LSTM-CNNs(基于双向LSTM神经网络的命名实体识别)论文阅读
  • buctoj_算法设计与分析(5)
  • Linux——Shell编程之循环语句(笔记)
  • 嵌入式系统的开发流程
  • 【AI论文】用于评估条件图像生成的统一代理框架
  • Spring 单元测试核心注解全解:@InjectMocks、@MockBean、@Mock、@Autowired 的区别与实战
  • 关于字节跳动旗下的豆包(DouBao)软件的详解、核心功能以及与同类产品的对比分析
  • 【C/C++】深入理解整型截断与提升:原理、应用与区别
  • 广东早熟荔枝“抢滩”上海,向长三角消费者喊话:包甜,管够
  • 威尼斯建筑双年展总策划:山的另一边有什么在等着我们
  • 人大新闻教育70年丨16759门课程里的时代密码
  • 均价19.5万元/平米!上海徐汇滨江地王项目“日光”,销售额近70亿元
  • 综艺还有怎样的新可能?挖掘小众文化领域
  • 湖北宜昌:在青山绿水间解锁乡村振兴“密码”