WebServer:buffer

news2024/9/21 22:30:17

这个应该是最先写的模块,因为缓冲区似乎是独立出来的。

buffer.h

sys/uio.h

这个头文件是Linux系统提供的用于IO操作的头文件,sys表明它是一个系统提供的头文件(类Unix系统提供的系统调用库似乎都是以sys开始的),uio表明它是一个Linux中的IO库(这个u我怀疑是Unix的意思)。
在该文件中,使用了其中的数据结构:

struct iovec { // 意思是io vector
    void  *iov_base;  // 指向缓冲区的指针
    size_t iov_len;   // 缓冲区的长度
};

和关于该数据结构的两个函数:

ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
ssize_t writev(int fd, const struct iovec *iov, int iovcnt);

使用iovec的好处在于:这两个函数能将一个文件描述符中的数据同时读/写到多个缓冲区中

ssizze_t和size_t的使用

在Buffer中,有很多在平时编写简短代码中不太常见的内容,如:size_tssize_t,这都是为了保证程序的可移植性,使用size_t作为函数返回值是为了和vector的size()匹配,而ssize_t则是因为和系统API进行了交互

ssize_t往往被声明为signed int

函数编写建议

因为上面这些小知识点,我们就能够得到一个结论:

  1. ssize_t:用于需要表示负值的场景,通常与系统API交互时,特别是在处理可能失败的操作和错误码时。
  2. size_t:用于处理不可能是负数的情况,如数组大小、容器容量和索引。

如果在编写程序的时候能够注意这些小问题,就能够提高我们编写的程序的可移植性。

关于调用系统调用

这个问题是源于Buffer的读写函数中:

ssize_t ReadFD(int fd, int* Errno);
ssize_t WriteFD(int fd, int* Errno);

[!问题描述]
系统调用不是会自动对一个全局变量errno进行设置吗?为什么这里还需要传入一个由我们维护的int* Errno

这是因为errno是一个全局变量,WebServer是一个多线程程序,在多线程中,直接使用errno很容易就会产生数据竞争的问题,而在单线程中,我们直接使用errno是没问题的

atomic的使用

C++参考手册其中有对atomic的详细描述,包括了C++20的,WebServer使用的标准好像是C++14,并没有用到20。

atomic的操作其实不算多:

#include <atomic>
std::atomic<int> example(100); // 定义一个int类型的atomic变量,并且将其值初始化为100
exampe = store(50); // 将值原子地变更为50
int value = example.load() // 读取值

以上是比较基础的用法,还有exchange()compare_exchange_weak()compare_exchange_strongis_lock_free()我这没说,我看了下感觉我用不上。

断言的使用

#include <cassert>
assert(condition);

当传入的condition为false的时候,断言就会被触发,它会调用abort()函数,终止程序的运行

assert的行为是可以被控制的,若是不想更改代码,同时又不希望assert被使用,可以定义一个宏:#define NDEBUG

在宏NDEBUG被声明的时候,assert不会被启用,即使它在2代码中被使用,也不会有任何行为。

这里我就发现很有意思的一点:

#define NDEBUG

#include <assert.h>

这种情况下,NDEBUG才是有效的;若是define的声明在头文件导入之后,这个宏就不会起作用了,这是因为在头文件定义的时候就定义了这一点,我看了下asseert.h中的内容,发现了如下两行:

If NDEBUG is defined, do nothing.
If not, and EXPRESSION is zero, print an error message and abort.

其中就提到了NDEBUG的用法。

这个现象的解释就是在include之后它会检查之前是否有define过该宏。

vector中的clear()

void Buffer::RetrieveAll() {
    // bzero(&buffer_[0], buffer_.size());
    /*
      原版使用的是上面的注释部分
      但是这部分GPT说已经不建议使用了
      因为不符合C语言的编写标准
    */
    memset(&buffer_[0], 0, buffer_.size());

    readPos_ = 0;
    writePos_ = 0;
}

迭代器的更深入理解

C++参考手册中说到:迭代器就是更为广义上的指针。所以它的使用和指针其实差不多,但是为什么我会写这个呢?

char* Buffer::BeginPtr_() {
    return &*buffer_.begin();
}

主要是这段代码在我一开始看的时候感觉有点莫名其妙,有点不是很理解为什么要这么写。但现在就能较好的说明它了:

[!解释]
对于begin()都很清楚返回值是一个迭代器,而迭代器是一个抽象的指针,它重载了指针的所有操作(解引用和取地址),并且效果和操作指针是一样的,但是迭代器毕竟不是指针。

arr.begin()就是获得arr的首部迭代器,而对其进行解引用就是获得arr的首部值,即:arr[0],再对其解引用就得到了头部的地址

string.data()

这个函数我一直都没怎么用过,因为我觉得这部分直接使用C语言的写法会更好一点,data()获得的是string的首部元素的地址,具体如下:

void Buffer::Append(const std::string& str) {
    Append(str.data(), str.size());
}

其实这段代码如果是我要写的话我应该会直接写&str[0],但是从代码的编写规范来说,我的写法是不那么“现代化C++”的,所以还是使用data()更好点。

static_cast

static_cast本身不会丢弃原对象的const和volatile属性

const int num = 10;
int temp = static_cast<int>(num);
temp = 12;

这里涉及到两个知识点:

  • static_cast 只是类型转换:
    • static_cast 进行的是类型转换,并不改变原始数据的 const 限制。它只是将 num 的值传递到 temp 中,temp 在这个过程中并不继承 const 限制。
  • const 限制在原始对象中有效:
    • const 限制仅对原始对象有效。在上面的例子中,num 是 const,所以你不能修改 num。但 temp 是一个新的 int 变量,它不受 num 的 const 限制影响。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2153462.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux网络-----传输层

前言 一.传输层&#xff1a; 数据要交接应用层先通过传输层&#xff08;给哪个程序发数据&#xff09; 传输层作用&#xff1a;负责数据能够从发送端传输接收端。对于应用层来说有许多服务&#xff0c;传输层怎么知道把数据发给那个应用服务&#xff1f; 这时就有了端口号&am…

BMC 虚拟i2c访问PCA9545(switch芯片)后面的设备,为什么找不到PCA9545?

1.说明 1.1 背景 无意中看到PCA9545(switch芯片)后面有设备&#xff0c;但是PCA9545设备本身是连接到物理设备i2c上的&#xff0c;然而扫描该物理i2c bus&#xff0c;却找不到该设备。此篇文章主要找一下该原因的。 1.2 参考代码 当前使用的是ast2600芯片&#xff0c;可参考…

Mudslide

作者未提供代码

Qt/C++ TCP调试助手V1.1 新增图像传输与接收功能(附发布版下载链接)

发布版本链接 通过百度网盘分享的文件&#xff1a;TCP调试助手V1.zip&#xff08;含客户端与服务器&#xff09; 链接&#xff1a;https://pan.baidu.com/s/14LTRPChPhYdwp_s6KeyBiA?pwdcedu 提取码&#xff1a;cedu 基于Qt/C实现了一款功能丰富的TCP服务器与客户端调试助手…

HT876 带任意限幅的10.9Wx2高保真音频功放

特点 可任意配置的限幅功能 自由选择音频限制幅度&#xff0c;使输出音频信号限制在固定 失真水平内 内置自动限温控制功能 支持AB类与D类切换 THDN:0.02%(VDD8.4V, RL 4Ω, fIN 1kHz, Po 2x1.0W, BTL) 输出功率(fIN1kHZ,THDN10%) 2x10.9W (VDD9.0V, RL4Ω, BTL) VDD供电范围:2…

【C++】模拟实现二叉搜索(排序)树

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:实战项目集 ⚙️操作环境:Visual Studio 2022 目录 一.了解项目功能 二.逐步实现项目功能模块及其逻辑详解 &#x1f4cc;实现BSTreeNode类模板 &#x1f38f;构造BSTreeNode类成员变量 &#x1f38f;实现BSTreeNode类构…

空间解析几何2:空间中两线段/直线的距离【附MATLAB代码】

目录 理论公式 MATLAB代码 理论公式 MATLAB代码 公式实现 function [dis,P,Q,t1,s1]line2LineDistance(A1,B1,C1,D1) %求两线段的最短距离 % input % A1,B1为线段一的两端点 C1,D1为线段二的两端点 % output % dis,为两线段的最短距离&#xff0c;P,Q为距离最短时在两线段上…

10.2 溪降技术:双重检查

目录 10.2 双重检查概览观看视频课程电子书&#xff1a;双重检查场景场景 1场景 2 个人责任示例 1示例 2 总结 10.2 双重检查 概览 俗话说&#xff1a;“江山易改&#xff0c;本性难移”。在我们开始体验峡谷探险时&#xff0c;培养良好的习惯对我们的进一步发展至关重要。在所…

Spring AOP的应用

目录 1、maven坐标配置与xml头配置 2、代理方式的选择与配置 3、AOP的三种配置方式 3.1、XML模式 3.1.1 创建目标类和方法 3.1.2 创建切面 3.1.3 切面xml配置与表达式说明 3.1.4 单测 3.2 纯注解模式 3.2.1 开启注解相关配置 3.2.2 创建目标类和方法 3.2.3 创建切面…

ChatGPT 4o 使用指南 (9月更新)

首先基础知识还是要介绍得~ 一、模型知识&#xff1a; GPT-4o&#xff1a;最新的版本模型&#xff0c;支持视觉等多模态&#xff0c;OpenAI 文档中已经更新了 GPT-4o 的介绍&#xff1a;128k 上下文&#xff0c;训练截止 2023 年 10 月&#xff08;作为对比&#xff0c;GPT-4…

java之斗地主部分功能的实现

今天我们要实现斗地主中发牌和洗牌这两个功能&#xff0c;该如何去实现呢&#xff1f; 1.创建牌类&#xff1a;52张牌每一张牌包含两个属性:牌的大小和牌的花色。 故我们优先创建一个牌的类(Card)&#xff1a;包含大小和花色。 public class Card { //单张牌的大小及类型/…

20240921在友善之臂的NanoPC-T6开发板上使用Rockchip原厂的Android12适配宸芯的数传模块CX6602N

127|console:/ # uname -a console:/ # ifconfig console:/ # ifconfig -a console:/ # ifconfig -a 130|console:/ # ifconfig usb0 192.168.42.130 console:/ # console:/ # ifconfig console:/ # iperf3 -s & iperf3 -c 192.168.42.130 -i 1 -t 30 20240921在友善之臂的…

828华为云征文|华为云Flexus云服务器X实例之openEuler系统下部署Grav内容管理系统

828华为云征文&#xff5c;华为云Flexus云服务器X实例之openEuler系统下部署Grav内容管理系统 前言一、Flexus云服务器X实例介绍1.1 Flexus云服务器X实例简介1.2 Flexus云服务器X实例特点1.3 Flexus云服务器X实例使用场景 二、Grav介绍2.1 CMS介绍2.2 Grav简介2.3 Grav特点2.4 …

TinyML-On-The-Fly: 实时、低功耗、低成本的微控制器嵌入式设备内计算机视觉技术用于无人机图像分类

这篇论文的标题是《TinyML-On-The-Fly: Real-Time Low-Power and Low-Cost MCU-Embedded On-Device Computer Vision for Aerial Image Classification》&#xff0c;作者是 Riya Samanta, Bidyut Saha, Soumya K. Ghosh&#xff0c;来自印度理工学院克勒格布尔分校。论文主要研…

电子元器件之MOS管,附上几个常用MOS管电路和仿真。

MOS管是一种常用的电子元器件。 1.MOS管的类别 MOSFET简称MOS&#xff0c;是一种绝缘栅型场效应管。按照类别可以分为增强型mos管和耗尽型mos管。 导电沟道的形成方式‌ 增强型MOS管&#xff1a;在没有外加电压时&#xff0c;源极和漏极之间没有导电沟道存在。只有当栅极电…

【玉米田】

题目 代码 #include <bits/stdc.h> using namespace std; typedef long long LL;const int mod 1e8; const int M 1 << 12; LL f[13][M]; int g[13]; vector<int> state; vector<int> p[M]; int n, m; bool check(int x) {return !(x & x <&…

攻防世界---->Windows_Reverse1(补)

做题笔记。 做题回顾。 假设&#xff0c;我们不知道地址随机怎么办&#xff1f;不能动调&#xff0c;只能静态分析。 下载 查壳 upx脱壳。 32ida打开。 动调报错。 重新打开&#xff0c;静态分析。 跟进关键函数。 不明白可以反汇编和汇编一起看。 溯源。 *decode 取值等于 by…

分布式锁之 防误删(优化之UUID防误删)

文章目录 1、AlbumInfoApiController --》testLock()2、AlbumInfoServiceImpl --》testLock()3、问题&#xff1a;删除操作缺乏原子性。 实现如下&#xff1a; 1、AlbumInfoApiController --》testLock() Tag(name "专辑管理") RestController RequestMapping(&quo…

【计网】从零开始掌握序列化与反序列化 --- 基础知识储备与程序重构

从零开始掌握序列化与反序列化 1 初识序列化与反序列化2 再谈Tcp协议3 程序重构3.1 Socket类3.2 回调函数设计3.3 最终的Tcp服务器类 1 初识序列化与反序列化 在刚学习计算机网络时&#xff0c;我们谈到过网络协议栈&#xff0c;其中最上层的就是应用层&#xff0c;那么这个应…

Qt圆角窗口

Qt圆角窗口 问题&#xff1a;自己重写了一个窗口&#xff0c;发现用qss设置圆角了&#xff0c;但是都不生效&#xff0c;不过子窗口圆角都生效了。 无边框移动窗口 bool eventFilter(QObject *watched, QEvent *evt) {static QPoint mousePoint;static bool mousePressed f…