一、系统架构概览
会议系统采用"主进程+线程池+进程池"的分层架构,实现高并发与业务隔离:
流程图说明:
- 客户端:作为外部请求发起方,连接到系统主进程。
- 主进程:系统核心控制节点,负责协调线程池和进程池。
- 线程池:由主进程管理,专门处理客户端的连接请求(如TCP连接建立、请求解析等)。
- 进程池:负责管理多个独立的“房间进程”,实现会议室的隔离和并发管理。
- 房间进程:每个进程对应一个会议室,内部包含发送线程池(用于高效处理消息推送),通过Unix域套接字与主进程通信(低延迟、高安全的本地进程间通信方式)。
这种架构通过“线程池处理连接 + 进程池隔离业务”的方式,兼顾了高并发处理能力和业务稳定性(单个房间故障不影响其他房间)。
核心组件角色
- 主进程:全局资源管理,进程池调度,状态监控
- 线程池:接收客户端连接,初步处理请求
- 房间进程:独立管理单个会议室,含1个接收线程+5个发送线程
- 通信管道:主进程与房间进程通过Unix域套接字通信
二、创建会议室完整流程
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. 流程步骤
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. 流程步骤
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
系统调用,处理中断重试逻辑。 - 数据读写:
Readn
和writen
保证TCP数据流的完整读写(解决短读短写问题);read_fd
和write_fd
支持通过Unix域套接字传递文件描述符(用于进程间传递客户端连接)。 - 辅助功能:
Sock_ntop
实现套接字地址到字符串的转换;Setsockopt
封装setsockopt
设置套接字选项(如SO_REUSEADDR
)。
网络模块通过统一的错误处理(依赖err_quit
、err_msg
)保证异常场景的可追溯性。
2. 线程与进程同步模块(unpthread.cpp、unpthread.h、msg.h)
系统采用多线程+多进程架构,同步机制是保证数据一致性的核心,主要组件包括:
- 线程操作封装:
Pthread_create
、Pthread_detach
等函数封装原生 pthread 接口,简化线程创建与管理,并统一错误处理。 - 互斥锁与条件变量:
Pthread_mutex_lock
、Pthread_mutex_unlock
封装互斥锁操作;Pthread_cond_wait
、Pthread_cond_signal
实现线程间等待/通知机制,用于消息队列的生产-消费同步。 - 消息队列(SEND_QUEUE):定义于
msg.h
,基于std::queue
实现线程安全的消息缓冲。通过互斥锁(lock
)保护队列操作,条件变量(cond
)协调生产者(push_msg
)和消费者(pop_msg
):当队列满时生产者等待,当队列空时消费者等待,消息入队/出队后通过信号唤醒等待线程。
3. 会议房间管理模块(room.cpp)
房间是系统的核心业务单元,负责管理会议内的用户及消息分发,主要功能包括:
- 房间生命周期管理:
clear_room
函数负责关闭房间内所有用户连接、清理用户数据(fdset
、status
、fdToIp
)及消息队列,将房间状态置为CLOSE
。 - 用户加入/退出处理:
accept_fd
线程负责接收新用户连接(通过进程间传递的文件描述符),根据操作类型(创建/加入会议)更新用户池(pool
),并发送会议响应或用户加入通知。fdclose
函数处理用户退出:若为房主退出则关闭整个房间,否则仅移除该用户并广播退出通知。
- 消息分发:
send_func
线程池从消息队列(sendqueue
)获取消息,根据消息类型(如IMG_RECV
、TEXT_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描述),确保错误场景的标准化处理,简化调试与问题定位。
核心设计优势
- 进程隔离:单个房间崩溃不影响其他会议,提高系统稳定性
- 并发优化:线程池处理连接突发,发送线程池避免消息阻塞
- 高效通信:Unix域套接字实现低延迟进程间通信,支持文件描述符传递
- 状态可见:主进程实时监控所有房间状态,支持动态调度
通过这种多层次的进程-线程协作架构,系统可支持500+并发用户、50+同时会议,消息转发延迟控制在50ms以内,满足实时会议的核心需求。