基于多反应堆的高并发服务器【C/C++/Reactor】(中)ChannelMap 模块的实现

(三)ChannelMap模块的实现

这个模块其实就是为Channel 来服务的,前面讲了Channel 这个结构体里边它封装了文件描述符。假如说我们得到了某一个文件描述符,需要基于这个文件描述符进行它对应的事件处理,那怎么办呢? 我们就需要找到文件描述符对应的那个Channel ,因为在这个Channel 里边有事件对应的回调函数,只有找到Channel 之后,我们才能够知道当读事件被触发了,或者说写事件被触发了。咱们调用的函数是什么呢?在C语言里,没有stl容器的,那如何实现一个对应关系呢?最简单的方式就是使用数组。有一种查找效率更高的数据结构就是哈希,其实它就是通过数组来实现的。 通过空间换时间,牺牲一部分内存空间换取数据的读取效率。看下图,对于每个数组来说,都有一个唯一的下标,是从零开始的,对于文件描述符来说,最小值也是零,所以我们可以让数组的下标去对应文件描述符,0号下标对应0号文件描述符,1号下标对应1号文件描述符。假设说和客户端建立了一个连接,得到了5号文件描述符,那么前边的这些文件描述符是不是有可能是空的?也就是说下标对应的值是空的,这个有关系吗?没关系啊,因为前边说的咱们实现的这种map,主要的思路是空间换时间,所以要换取效率,必然是要牺牲一部分空间的。使用了这种方式,就直接能够通过下标来取出对应的值,不需要遍历。

主要介绍了ChannelMap 的实现思路,包括使用数组和哈希 等数据结构,以及如何通过空间换时间来提高查找效率。同时,还介绍了如何定义map对应的那个结构体,以及如何实例化这个数组。

核心观点:

  1. 使用数组或哈希等数据结构实现ChannelMap,以提高查找效率。
  2. 通过空间换时间的思想,牺牲一部分空间来换取效率。
  3. map对应的结构体中,主要的数据成员是一个数组,数组的大小需要根据实际情况确定。
  4. 需要实例化数组,并确定数组中存储的指针类型。

ChannelMap相关函数

(1) channelMapInit

功能:为ChannelMap分配内存

  1. 分配内存给指针。
  2. 计算内存大小:size * 指针的字节数(指针为4字节)。
  3. map指针的地址返回给调用者。

(2) ChannelMapClear

功能:清空ChannelMap结构体。

  1. 判断map是否为空。
  2. 遍历数组,释放指针指向的内存(如果指针不为空)。
  3. 释放数组指向的内存。
  4. 将数组的size置为0。

注意事项:内存释放分为两部分,数组元素指向的内存和数组本身指向的内存。

(3) makeMapRoom数组扩容函数

功能:判断并扩容ChannelMap 中的list

  1. 判断当前listsize 是否大于newSize
  2. 如果需要扩容,调用realloc 函数重新分配更大的内存给list

注意事项:只有当map 中的size 小于newSize 时才需要进行扩容操作

  • Channel.h
cpp 复制代码
#pragma once
#include "Channel.h"
struct ChannelMap {
    struct Channel** list;
    int size;// 记录指针指向的数组的元素总个数
};

// 初始化
struct ChannelMap* channelMapInit(int size);

// 清空map
void ChannelMapClear(struct ChannelMap* map);

// 重新分配内存空间
bool makeMapRoom(struct ChannelMap* map,int newSize,int unitSize);
  • Channel.c
cpp 复制代码
#include "ChannelMap.h"
#include <stdio.h>
#include <stdlib.h>
struct ChannelMap* channelMapInit(int size) {
    struct ChannelMap* map = malloc(sizeof(struct ChannelMap));
    map->size = size;
    map->list = (struct Channel**)malloc(sizeof(struct Channel*) * size);
    return map;
}

void ChannelMapClear(struct ChannelMap* map) {
    if(map != NULL) {
        for(int i=0;i<map->size;++i) {
            if(map->list[i] != NULL) {
                free(map->list[i]);
            }
        }
        free(map->list);
        map->list = NULL;
    }
    map->size=0;
}

bool makeMapRoom(struct ChannelMap* map,int newSize,int unitSize) {
    if(map->size < newSize) {
        int curSize = map->size;
        // 容量每次扩大原来的一倍
        while(curSize < newSize) {
            curSize*=2;
        }
        // 扩容 realloc
        struct Channel** temp = realloc(map->list,curSize * unitSize);
        if(temp == NULL) {
            return false;
        }
        map->list = temp;
        memset(&map->list[map->size],0,(curSize - map->size) * unitSize);
        map->size = curSize;
    }
    return true;
}

第一个精彩片段:channelMapInit 函数的实现,详细介绍了如何为ChannelMap 分配内存,包括计算内存大小和返回map指针的地址。对于理解ChannelMap如何创建和初始化非常重要,有助于理解后续的函数如何工作。

第二个精彩片段:ChannelMapClear 函数的实现,详细介绍了如何清空ChannelMap 结构体,包括释放内存和重置size。 这个片段对于理解如何管理和释放内存资源非常重要,有助于避免内存泄漏和其他相关问题。

内容概要:详细介绍了三个函数:channelMapInitChannelMapClearmakeMapRoom 对数组扩容函数的实现。这三个函数用于创建、初始化、清空和释放ChannelMap的内存,以及在必要时扩容数组。

核心观点:

  1. channelMapInit 函数主要负责为ChannelMap分配内存,包括为指针成员分配内存,并根据元素个数和指针的字节数计算内存大小。
  2. ChannelMapClear 函数用于清空ChannelMap 结构体,包括释放数组元素指向的内存和数组本身指向的内存,并将数组的size置为0。
  3. 对数组扩容函数需要判断当前数组的size 是否小于newSize ,如果需要扩容,则调用realloc函数重新分配更大的内存给数组。
相关推荐
秋已杰爱1 个月前
项目模块十七:HttpServer模块
高并发服务器
呵呵哒( ̄▽ ̄)"1 年前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)HttpRequest模块 解析http请求协议
基于多反应堆的·高并发服务器·c/c++/reactor
_snowstorm_1 年前
Linux学习之网络编程3(高并发服务器)
linux·服务器·学习·高并发服务器·多进程高并发服务器·多线程高并发服务器
呵呵哒( ̄▽ ̄)"1 年前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)完整代码
高并发服务器·c/c++/reactor·多反应堆
呵呵哒( ̄▽ ̄)"1 年前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)HttpResponse的定义和初始化 以及组织 HttpResponse 响应消息
基于多反应堆的·高并发服务器·c/c++/reactor
呵呵哒( ̄▽ ̄)"1 年前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)HttpRequest 提取请求行、解析请求行和优化 以及解析请求头并存储
请求行·请求头·基于多反应堆的·高并发服务器·c/c++/reactor
呵呵哒( ̄▽ ̄)"1 年前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)创建一个TcpConnection实例 以及 接收客户端数据
基于多反应堆的·高并发服务器·c/c++/reactor
呵呵哒( ̄▽ ̄)"1 年前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)处理任务队列中的任务
删除·基于多反应堆的·高并发服务器·c/c++/reactor·处理任务队列中的任务·添加·修改
呵呵哒( ̄▽ ̄)"1 年前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)主线程给子线程添加任务以及如何处理该任务
基于多反应堆的·高并发服务器·c/c++/reactor
呵呵哒( ̄▽ ̄)"1 年前
基于多反应堆的高并发服务器【C/C++/Reactor】(中)子线程 WorkerThread的实现 和 线程池ThreadPool的初始化
高并发服务器·c/c++/reactor·多反应堆·workerthread的实现