webserver服务器从零搭建到上线(六)|Timestamp类和InetAddress类

本节我们重点来谈论:

时间类和我们的初始化链接地址类

文章目录

Timestamp类

我们为什么要封装一个时间类呢?

这也是一个大型项目必须的基础组建,这样我们不仅可以提高代码的可读性,并且封装细节避免了直接操作时间时可能引发的错误,提高代码的健壮性。

cpp 复制代码
//时间类
class Timestamp {
public:
    Timestamp();
    explicit Timestamp(int64_t microSecondsSinceEpoch_);

    //返回当前时间-长整形
    static Timestamp now();

    //将长整型转换为年月日字符串
    std::string toString() const;
private:
    int64_t microSecondsSinceEpoch_;
};

时间类的作用主要就是以上几个:

  • 获取当前时间,返回值是一个长整型
  • 长整型转换为年月日

调用方式应为:

cpp 复制代码
int main () {
	cout << Timestamp::now().toString() << endl
	return 0;
}

成员函数实现

cpp 复制代码
#include "Timestamp.h"

#include <time.h>

Timestamp::Timestamp(): microSecondsSinceEpoch_(0) {}

Timestamp::Timestamp(int64_t microSecondsSinceEpoch)
    : microSecondsSinceEpoch_(microSecondsSinceEpoch)
    {}

Timestamp Timestamp::now()
{
	//返回对象实例,对象成员变量是当前的 int64_t
    return Timestamp(time(NULL));
}

std::string Timestamp::toString() const
{
    char buf[128] = { 0 };
    tm *tm_time = localtime(&microSecondsSinceEpoch_);
    snprintf(buf, 128, "%4d/%02d/%02d %02d:%02d:%02d", 
        tm_time->tm_year + 1900, 
        tm_time->tm_mon + 1,
        tm_time->tm_mday,
        tm_time->tm_hour,
        tm_time->tm_min,
        tm_time->tm_sec);
    return buf;
}

time(NULL)返回一个 64 位整数,是自 Unix 纪元(1970 年 1 月 1 日 00:00:00 UTC)以来的时间,变量类型为int64_t

InetAddress类

该类也比较简单,就是封装 socket 地址的类型

cpp 复制代码
class InetAddress {
public:
    explicit InetAddress(uint16_t port, std::string ip = "127.0.0.1");
    explicit InetAddress(const sockaddr_in &addr)
        : addr_(addr)
    {}

    std::string toIP() const;
    std::string toIpPort() const;
    uint16_t toPort() const;

    const sockaddr_in* getSockAddr() const {return &addr_;}

private:
    sockaddr_in addr_;
};
  • toIP()返回 InetAddress 对象中存储的 IP 地址的字符串表示
  • toIpPort()返回 InetAddress 对象中存储的 IP 地址和端口号的字符串表示,格式为 IP:Port
  • toPort()返回 InetAddress 对象中存储的端口号。
  • getSockAddr()返回指向内部 sockaddr_in 结构体的指针,方便在其他网络操作中使用。
  • 私有成员变量 sockaddr_in addr_:存储 IP 地址和端口号的结构体,包含了网络地址信息。

该类的主要作用就是:

  • 提供对 IP 地址和端口号的封装,便于在网络编程中管理和使用;
  • 提供方便的方法来获取和表示网络地址和端口的信息;
  • 通过提供的函数,能够轻松地转换地址和端口信息为字符串格式,便于调试和日志记录。

具体实现

cpp 复制代码
InetAddress::InetAddress(uint16_t port, std::string ip) {
    bzero(&addr_, sizeof addr_);
    addr_.sin_family = AF_INET;
    addr_.sin_port = htons(port);
    addr_.sin_addr.s_addr = inet_addr(ip.c_str());
}

std::string InetAddress::toIP() const
{
    //addr_
    char buf[64] = {0};
    ::inet_ntop(AF_INET, &addr_.sin_addr, buf, sizeof buf);
    return buf;
}

std::string InetAddress::toIpPort() const
{
    //ip: port
    char buf[64] = {0};
    ::inet_ntop(AF_INET, &addr_.sin_addr, buf, sizeof buf);
    size_t end = strlen(buf);
    uint16_t port = ntohs(addr_.sin_port);
    sprintf(buf+end, ":%u", port);
    return buf;
}

uint16_t InetAddress::toPort() const
{
    return ntohs(addr_.sin_port);
}

我们可以看出,构造函数已经为我们封装好了sockaddr_in的配置,我们只需要传入ip和port即可

然后这里主要解释几个函数:

cpp 复制代码
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

inet_ntop(AF_INET, &addr_.sin_addr, buf, sizeof buf);

inet_ntop 是一个用于将网络地址转换为字符串表示的函数.

af:地址族,通常为 AF_INET(表示 IPv4)或 AF_INET6(表示 IPv6)。
src:指向存储有IP的结构体。
dst:指向用于存储转换后的字符串的缓冲区。
size:缓冲区的大小。

cpp 复制代码
int sprintf(char *str, const char *format, ...);

sprintf(buf + end, ":%u", port);

sprintf 是一个 C 标准库函数,用于将格式化的数据写入字符串中。

这里的buf+end其实就是接着之前写进去的ip后面继续写port端口。

相关推荐
耶啵奶膘39 分钟前
uniapp-是否删除
linux·前端·uni-app
pianmian11 小时前
python数据结构基础(7)
数据结构·算法
2401_850410832 小时前
文件系统和日志管理
linux·运维·服务器
王哈哈^_^2 小时前
【数据集】【YOLO】【目标检测】交通事故识别数据集 8939 张,YOLO道路事故目标检测实战训练教程!
前端·人工智能·深度学习·yolo·目标检测·计算机视觉·pyqt
cs_dn_Jie3 小时前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
好奇龙猫3 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
开心工作室_kaic3 小时前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
一只哒布刘3 小时前
NFS服务器
运维·服务器
有梦想的刺儿4 小时前
webWorker基本用法
前端·javascript·vue.js
sp_fyf_20244 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘