1.原理
客户端从标准输入读取数据,将数据序列化后发送至网络;
服务器端使用多线程+生产者消费者模型
生产者从网络中读取数据,并将读取到的用户信息添加至用户列表中,将数据放至数据池中;
消费者从数据池读取数据,并广播给所有在用户列表中的用户;
数据经过网络以后,反序列化再次发给客户端,实现群聊功能;
2.所用技术
平台: CentOS 7, 64位操作系统
语言: C/C++
编译工具: g++
序列化反序列化工具: jsoncpp
窗口设计框架: nucrse/ncurses
其他: 生产者消费者模型、信号量互斥机制、多线程编程、socket套接字编程
3.系统框架
server模块: 收到用户发送的字符串以后, 将用户信息存储到在线用户表中,将数据存储到数据池中, 再将数据广播给所有在线用户;
client模块: 从标准输入读取用户数据,并且将字符串序列化,发送给服务器; 接收到服务器的数据以后,反序列化,输出到output框;
data_pool模块: 数据池,存放用户发过来的诗句,是一个环形队列描述的;
window模块: 显示用户界面,使用ncurses库实现;
4.具体模块
server:
部分成员函数:
addrUser: 将用户添加至online中
delUser: 将用户online中删除
RecvDate: 接收客户端发送到网络中的数据,并且判断用户的cmd状态是不是"QUIT",就调用del从online中删除,如果用户状态不为"QUIT",就将用户数据存放到数据池
SendData: 将数据发给所有才online列表中的用户
部分成员变量:
std::map
data_pool pool: 后面讲解;
clinet:
client这里的定义比较简单,进行数据的收发,但是主逻辑部分实现逻辑就比较复杂了
首先,我们使用多线程,为了使用户端聊天室的每一个部分都独立(主要分为欢迎头部,输出框,和输入框)
欢迎头部的功能就是滚动的播放welcome
输出框又分为了输出用户信息和在线成员,并且实现框满清屏的效果
输入框使用户用来输入消息,按回车键就发送出去
data_pool:
data_pool是实现一个数据池,讲用户发来的数据都存储在数据池中,服务器要广播数据的时候,也会从数据池中拿数据。
这里使用生产者消费者模型,完成资源的同步与互斥,使用vector维护一个环形队列,生产者只在意当前环形队列的空白个数,消费者只在意当前的数据个数。
window:
因为在客户端是多线程并发执行数据,我们这里使用互斥锁来保证线程安全。
window模块主要是实现客户端界面,设计效果如下
comm:
这一部分主要实数据的序列化和反序列化,使用 jsoncpp
并且将序列化和反序列化进行简单的封装
发送的数据会有 昵称、学校、消息内容、状态信息,客户端将这些信息发送出去以后,在网络中会序列化为一个字符串,服务器接收到数据以后,再将字符串反序列化为用户信息,进行存储和处理。
5.效果演示
6.代码链接
聊一聊系统