会议系统核心流程详解:创建、加入与消息交互

发布于:2025-08-17 ⋅ 阅读:(19) ⋅ 点赞:(0)

一、系统架构概览

会议系统采用"主进程+线程池+进程池"的分层架构,实现高并发与业务隔离:

Unix域套接字通信
Unix域套接字通信
客户端
主进程
线程池
处理连接接收
进程池
管理会议室
房间进程1
含发送线程池
房间进程2
含发送线程池
房间进程N
含发送线程池

流程图说明:

  1. 客户端:作为外部请求发起方,连接到系统主进程。
  2. 主进程:系统核心控制节点,负责协调线程池和进程池。
  3. 线程池:由主进程管理,专门处理客户端的连接请求(如TCP连接建立、请求解析等)。
  4. 进程池:负责管理多个独立的“房间进程”,实现会议室的隔离和并发管理。
  5. 房间进程:每个进程对应一个会议室,内部包含发送线程池(用于高效处理消息推送),通过Unix域套接字与主进程通信(低延迟、高安全的本地进程间通信方式)。

这种架构通过“线程池处理连接 + 进程池隔离业务”的方式,兼顾了高并发处理能力和业务稳定性(单个房间故障不影响其他房间)。

核心组件角色

  • 主进程:全局资源管理,进程池调度,状态监控
  • 线程池:接收客户端连接,初步处理请求
  • 房间进程:独立管理单个会议室,含1个接收线程+5个发送线程
  • 通信管道:主进程与房间进程通过Unix域套接字通信

二、创建会议室完整流程

1. 流程步骤

客户端 线程池线程 主进程 房间进程(空闲) 发送 CREATE_MEETING 请求 请求分配空闲房间 查找空闲房间进程(遍历room->>pptr) 返回房间索引i 通过管道传递connfd+命令'C' 接收线程(accept_fd)处理连接 标记客户端为房主(user_pool->>owner) 返回会议室创建成功 状态更新为"忙碌"(child_status=1) 客户端 线程池线程 主进程 房间进程(空闲)

2. 关键技术细节

  • 房间分配机制:主进程通过遍历room->pptr数组查找child_status=0的空闲进程,加锁保证线程安全

    // 核心代码:查找空闲房间
    pthread_mutex_lock(&room->lock);
    for (int i=0; i<room->num; i++) {
        if (room->pptr[i].child_status == 0) {  // 找到空闲房间
            room->pptr[i].child_status = 1;     // 标记忙碌
            room->navail--;
            break;
        }
    }
    pthread_mutex_unlock(&room->lock);
    
  • 连接交接技术:通过Unix域套接字传递客户端连接(connfd),使用SCM_RIGHTS控制消息实现文件描述符跨进程传递

    // 传递连接核心代码
    struct cmsghdr *cmptr = CMSG_FIRSTHDR(&msg);
    cmptr->cmsg_type = SCM_RIGHTS;
    *(int*)CMSG_DATA(cmptr) = client_fd;  // 传递文件描述符
    sendmsg(pipefd, &msg, 0);
    

三、加入会议完整流程

1. 流程步骤

客户端 线程池线程 主进程 目标房间进程(忙碌) 房间内其他客户端 发送 JOIN_MEETING(房间ID) 请求 请求连接目标房间ID 通过管道传递connfd+命令'J' 接收线程添加用户到user_pool 广播"新用户加入"通知 返回加入成功 更新用户数(total++) 客户端 线程池线程 主进程 目标房间进程(忙碌) 房间内其他客户端

2. 关键技术细节

  • 用户池管理:房间进程通过user_pool结构体维护所有参会者连接,使用文件描述符集合(fdset)监控活动

    // 房间内用户管理
    Pthread_mutex_lock(&user_pool->lock);
    FD_SET(client_fd, &user_pool->fdset);  // 添加新用户
    user_pool->num++;                      // 增加用户计数
    Pthread_mutex_unlock(&user_pool->lock);
    
  • 广播通知机制:新用户加入后,房间进程向所有已连接用户发送通知,确保参会者列表同步

四、消息收发与转发流程

1. 流程步骤

发送客户端 房间进程 发送线程池 接收客户端1 接收客户端2 发送消息(文字/图片) 主线程读取消息头解析类型 完整接收消息体 将消息加入发送队列 转发消息(含发送者信息) 转发消息(含发送者信息) 消息发送完成确认 发送客户端 房间进程 发送线程池 接收客户端1 接收客户端2

2. 关键技术细节

  • 多线程协作:房间进程采用"1个接收线程+5个发送线程"的模型,解耦消息接收与转发

    // 发送线程池初始化
    for (int i=0; i<SENDTHREADSIZE; i++) {  // SENDTHREADSIZE=5
        Pthread_create(&tid, NULL, send_func, NULL);
    }
    
  • 消息队列缓冲:使用线程安全的消息队列(send_queue)平衡发送负载,避免消息阻塞

    // 消息入队
    Pthread_mutex_lock(&queue.lock);
    queue.send_queue.push(msg);  // 存入消息
    Pthread_cond_signal(&queue.cond);  // 唤醒发送线程
    Pthread_mutex_unlock(&queue.lock);
    
  • 协议格式设计:消息采用固定格式头部($_类型_IP_长度_),解决TCP粘包问题

    示例:$_TEXT_192.168.1.10_0005_Hello_#
    格式:$_[类型]_[IP]_[长度]_[内容]_#
    

五、进程与线程协作关系总结

组件 角色职责 通信方式
主进程 进程池管理、状态监控、资源调度 Unix域套接字(与房间进程)
线程池线程 接收客户端连接、初步请求处理 共享内存(主进程状态)
房间进程主线程 监控用户活动、接收消息 管道(与主进程)
房间接收线程 处理新用户加入、连接交接 内部信号量
发送线程池 消息转发、负载均衡 消息队列(线程间)

六、模块设计

1. 网络通信模块(net.cpp、netheader.h)

网络通信是系统的基础支撑,负责TCP连接的建立、数据传输及底层网络操作封装,主要功能包括:

  • 连接管理:通过Tcp_listen创建监听套接字,支持IPv4/IPv6双栈;Tcp_connect实现客户端与服务器的连接;Accept封装accept系统调用,处理中断重试逻辑。
  • 数据读写Readnwriten保证TCP数据流的完整读写(解决短读短写问题);read_fdwrite_fd支持通过Unix域套接字传递文件描述符(用于进程间传递客户端连接)。
  • 辅助功能Sock_ntop实现套接字地址到字符串的转换;Setsockopt封装setsockopt设置套接字选项(如SO_REUSEADDR)。

网络模块通过统一的错误处理(依赖err_quiterr_msg)保证异常场景的可追溯性。

2. 线程与进程同步模块(unpthread.cpp、unpthread.h、msg.h)

系统采用多线程+多进程架构,同步机制是保证数据一致性的核心,主要组件包括:

  • 线程操作封装Pthread_createPthread_detach等函数封装原生 pthread 接口,简化线程创建与管理,并统一错误处理。
  • 互斥锁与条件变量Pthread_mutex_lockPthread_mutex_unlock封装互斥锁操作;Pthread_cond_waitPthread_cond_signal实现线程间等待/通知机制,用于消息队列的生产-消费同步。
  • 消息队列(SEND_QUEUE):定义于msg.h,基于std::queue实现线程安全的消息缓冲。通过互斥锁(lock)保护队列操作,条件变量(cond)协调生产者(push_msg)和消费者(pop_msg):当队列满时生产者等待,当队列空时消费者等待,消息入队/出队后通过信号唤醒等待线程。

3. 会议房间管理模块(room.cpp)

房间是系统的核心业务单元,负责管理会议内的用户及消息分发,主要功能包括:

  • 房间生命周期管理clear_room函数负责关闭房间内所有用户连接、清理用户数据(fdsetstatusfdToIp)及消息队列,将房间状态置为CLOSE
  • 用户加入/退出处理
    • accept_fd线程负责接收新用户连接(通过进程间传递的文件描述符),根据操作类型(创建/加入会议)更新用户池(pool),并发送会议响应或用户加入通知。
    • fdclose函数处理用户退出:若为房主退出则关闭整个房间,否则仅移除该用户并广播退出通知。
  • 消息分发send_func线程池从消息队列(sendqueue)获取消息,根据消息类型(如IMG_RECVTEXT_RECV)向房间内指定用户(或所有用户)转发数据,确保消息格式统一($_msgType_ip_size_data_#)。

4. 用户请求处理模块(userdeal.cpp)

该模块负责解析客户端请求并协调房间资源,核心逻辑在dowithuser函数中:

  • 请求解析:读取客户端消息头(11字节,包含消息类型、IP、数据长度),解析出CREATE_MEETING(创建会议)、JOIN_MEETING(加入会议)等请求类型。
  • 资源协调:创建会议时检查进程池(room)是否有空闲房间,若有则通过write_fd向对应房间进程传递客户端连接;加入会议时验证房间有效性,通过房间进程的管道传递连接并返回结果。

5. 主程序与进程/线程池(main.cpp)

main.cpp是系统入口,负责初始化核心资源并协调各模块运行:

  • 进程池初始化:通过process_make创建多个子进程(每个对应一个房间),父子进程通过Unix域套接字对(socketpair)通信,父进程监控子进程状态(房间是否空闲)。
  • 线程池初始化:通过thread_make创建多个工作线程,负责处理客户端初始连接(调用dowithuser)。
  • 主循环:通过select监控进程池管道,处理房间状态更新(如房间空闲、用户退出),维护全局资源的一致性。

6. 错误处理模块(error.cpp)

系统通过err_quit(退出程序)、err_msg(仅打印错误)统一处理错误,基于err_doit函数格式化错误信息(包含errno描述),确保错误场景的标准化处理,简化调试与问题定位。

核心设计优势

  1. 进程隔离:单个房间崩溃不影响其他会议,提高系统稳定性
  2. 并发优化:线程池处理连接突发,发送线程池避免消息阻塞
  3. 高效通信:Unix域套接字实现低延迟进程间通信,支持文件描述符传递
  4. 状态可见:主进程实时监控所有房间状态,支持动态调度

通过这种多层次的进程-线程协作架构,系统可支持500+并发用户、50+同时会议,消息转发延迟控制在50ms以内,满足实时会议的核心需求。


网站公告

今日签到

点亮在社区的每一天
去签到