从零开始实现一个C++高性能服务器框架----Address模块

简介

项目介绍:实现了一个基于协程的服务器框架,支持多线程、多协程协同调度;支持以异步处理的方式提高服务器性能;封装了网络相关的模块,包括socket、http、servlet等,支持快速搭建HTTP服务器或WebSokcet服务器。

详细内容:日志模块,使用宏实现流式输出,支持同步日志与异步日志、自定义日志格式、日志级别、多日志分离等功能。线程模块,封装pthread相关方法,封装常用的锁包括(信号量,读写锁,自旋锁等)。IO协程调度模块,基于ucontext_t实现非对称协程模型,以线程池的方式实现多线程,多协程协同调度,同时依赖epoll实现了事件监听机制。定时器模块,使用最小堆管理定时器,配合IO协程调度模块可以完成基于协程的定时任务调度。hook模块,将同步的系统调用封装成异步操作(accept, recv, send等),配合IO协程调度能够极大的提升服务器性能。Http模块,封装了sokcet常用方法,支持http协议解析,客户端实现连接池发送请求,服务器端实现servlet模式处理客户端请求,支持单Reator多线程,多Reator多线程模式的服务器。

Address模块

1. 主要功能

  • 对Linux下ipv4和ipv6地址的封装
  • 提供网络地址相关的类,支持与网络地址相关的操作,包括域名解析,网卡地址查询等

2. 功能演示

  • 根据域名获取一个IP地址
Address::ptr addr = Address::LookupAnyIPAddress("www.baidu.com:80");
  • 根据"ipv4的字符串格式"获取一个IP地址
IPv4Address::ptr addr = IPv4Address::Create("192.168.2.13", 9999);

3. 模块介绍

3.1 Address

  • 所有网络类的基类,是对sockaddr的封装。主要关注地址类型,sockaddr指针,地址长度等内容。同时,还支持地址解析和本地网卡地址查询功能。
 class Address
 {
  public:
      typedef std::shared_ptr<Address> ptr;
      ....
 }
  • 地址解析。实现域名解析
 // 通过host地址返回对应条件的所有Address,结果保存到result
 bool Address::Lookup(std::vector<Address::ptr>& result, const std::string& host,
                  int family, int type, int protocol) {
     addrinfo hints, *results, *next;
     hints.ai_flags = 0;
     hints.ai_family = family;
     hints.ai_socktype = type;
     hints.ai_protocol = protocol;
     hints.ai_addrlen = 0;
     hints.ai_canonname = NULL;
     hints.ai_addr = NULL;
     hints.ai_next = NULL;

     std::string node;
     const char* service = NULL;

     //检查 ipv6address serivce
     //host: 
     if(!host.empty() && host[0] == '[') {
         const char* endipv6 = (const char*)memchr(host.c_str() + 1, ']', host.size() - 1);
         if(endipv6) {
             //TODO check out of range
             if(*(endipv6 + 1) == ':') {
                 service = endipv6 + 2;
             }
             node = host.substr(1, endipv6 - host.c_str() - 1);
         }
     }

     //检查 node serivce
     if(node.empty()) {
         service = (const char*)memchr(host.c_str(), ':', host.size());
         if(service) {
             if(!memchr(service + 1, ':', host.c_str() + host.size() - service - 1)) {
                 node = host.substr(0, service - host.c_str());
                 ++service;
             }
         }
     }

     if(node.empty()) {
         node = host;
     }
     int error = getaddrinfo(node.c_str(), service, &hints, &results);
     if(error) {
         LOG_DEBUG(g_logger) << "Address::Lookup getaddress(" << host << ", "
             << family << ", " << type << ") err=" << error << " errstr="
             << gai_strerror(error);
         return false;
     }

     next = results;
     while(next) {
         result.push_back(Create(next->ai_addr, (socklen_t)next->ai_addrlen));
         next = next->ai_next;
     }

     freeaddrinfo(results);
     return !result.empty();
 }
  • 获取网卡地址
// 返回本机所有网卡的<网卡名, 地址, 子网掩码位数>
static bool GetInterfaceAddresses(std::multimap<std::string
                ,std::pair<Address::ptr, uint32_t> >& result, int family = AF_INET);

3.2 IPAddress

  • 表示网络地址类。继承自Address类,表示一个IP地址,同样是一个抽象类,因为IP地址包含IPv4地址和IPv6地址。IPAddress类提供了IP地址相关的端口和掩码、网段地址、网络地址操作,无论是IPv4还是IPv6都支持这些操作,但这些方法都是抽象方法,需要由继承类来实现。
class IPAddress : public Address
{
public:
    typedef std::shared_ptr<IPAddress> ptr;

	// 通过域名,IP,服务器名创建IPAddress
    static IPAddress::ptr Create(const char* address, uint16_t port = 0);

	// 获取该地址的广播地址
    virtual IPAddress::ptr broadcastAddress(uint32_t prefix_len) = 0;

	// 获取该地址的网段
    virtual IPAddress::ptr networdAddress(uint32_t prefix_len) = 0;

	// 获取子网掩码地址
    virtual IPAddress::ptr subnetMask(uint32_t prefix_len) = 0;
	
	// 返回端口号
    virtual uint16_t getPort() const = 0;

	// 设置端口号
    virtual void setPort(uint16_t v) = 0;
};

3.3 IPv4Address

  • 继承自IPAddress类,表示一个IPv4地址。它包含一个sockaddr_in类型的成员,并且提供具体的端口设置/获取,掩码、网段、网络地址设置/获取操作。用于给定一个“ip地址(192.168.2.13)”或二进制ip地址,返回一个封装好的IPv4Address对象
class IPv4Address : public IPAddress
{
public: 
    typedef std::shared_ptr<IPv4Address> ptr;

	// sockaddr_in构造IPv4Address
    IPv4Address(const sockaddr_in& address);
	
	// 通过二进制地址构造IPv4Address
    IPv4Address(uint32_t address = INADDR_ANY, uint16_t port = 0);

    static IPv4Address::ptr Create(const char* ip, uint16_t port);

    const sockaddr* getAddr() const override;
    sockaddr* getAddr() override;
    socklen_t getAddrLen() const override;
    std::ostream& insert(std::ostream& os) const override;

    IPAddress::ptr broadcastAddress(uint32_t prefix_len) override;
    IPAddress::ptr networdAddress(uint32_t prefix_len) override;
    IPAddress::ptr subnetMask(uint32_t prefix_len) override;
    uint16_t getPort() const override;
    void setPort(uint16_t v) override;

private:
    sockaddr_in m_addr;
};

3.4 IPv6Address

  • 继承自IPAddress类,表示一个IPv6地址。用于给定一个“ipv6地址”或二进制ipv6地址,返回一个封装好的IPv6Address对象
class IPv6Address : public IPAddress {
public:
     typedef std::shared_ptr<IPv6Address> ptr;
		
	 // 通过IPv6地址字符串构造IPv6Address
     static IPv6Address::ptr Create(const char* address, uint16_t port = 0);
     IPv6Address();

	 // 通过sockaddr_in6构造IPv6Address
     IPv6Address(const sockaddr_in6& address);
	 
	 // 通过IPv6二进制地址构造IPv6Address
     IPv6Address(const uint8_t address[16], uint16_t port = 0);

     const sockaddr* getAddr() const override;
     sockaddr* getAddr() override;
     socklen_t getAddrLen() const override;
     std::ostream& insert(std::ostream& os) const override;

     IPAddress::ptr broadcastAddress(uint32_t prefix_len) override;
     IPAddress::ptr networdAddress(uint32_t prefix_len) override;
     IPAddress::ptr subnetMask(uint32_t prefix_len) override;
     uint16_t getPort() const override;
     void setPort(uint16_t v) override;
 private:
     sockaddr_in6 m_addr;
 };
  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熬夜写代码的平头哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值