1 获取在线列表功能实现
1.1 、客户端
这个功能,客户端的组包和解包的实现,和上一节的类似。
只是要注意:
为实时获得在线情况,我们需要用到定时器。通过定时器,周期的发送 获取在线列表 的数据包。
1.2 服务器端
为了能够保存客户端登录信息,我们使用链表,对客户端的登录信息进行保存。
这里用到了链表的基本操作。参考博客:
https://blog.csdn.net/cainiaofu/article/details/108534731
2、聊天功能的实现
2.1预期效果
点击在线用户列表中的某个ID,弹出对应的对话框。通过这个对话框,和这个ID聊天。
2.2 实现流程
假设现在有两个客户端(15和16),他们要将进行聊天。
我们在客户端15的列表中,点击16;表示要和16进行聊天。
我们在双击16的时候,通过信号与槽,创建和16的聊天界面。
这部分的代码如下:
//QModelIndex:被点击的文本 如果是和他人聊天,这个文本的内容就是对端ID
connect(_list, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(showChatDialog(QModelIndex)));
在槽函数,做的事情是:
在客户端15上创建与客户端16的聊天界面。当按下发送按钮的时候,客户端15会发送给服务器 聊天数据包(自己组的),告诉服务器,我要和客户端16聊天,并告诉服务器,我要发给16的内容。服务器,解析以后,会发送给客户端16一个数据包。客户端16解析这个数据包以后,会再次调用创建聊天界面的函数,在客户端16上创建与客户端15的聊天界面,并显示客户端15发来的数据。
//获取聊天信息
QByteArray chatData = buf.mid(index, buf.length() - index - 1);
//找到我们目的界面
ChatDialog* chatDialog = findChatDialog(otherID);
//在目的界面显示信息
chatDialog->setChatList(chatData);
chatDialog->show();
2.3 关键问题:如何做到不重复创建聊天界面
为了解决这个问题,我们使用map容器。
以客户端15为例:假设现在同时有8个人在线,我要和这8个人聊天。我将在第一次和他们聊天的时候,创建聊天界面。并将这个界面的的ID保存在map容器中。
QMap <QString, ChatDialog*> _chatDialogMap;
_chatDialogMap.insert(ID, chatDialog);
与其他用户聊天同理,都是在第一次聊天的时候,将ID保存在这个容器中。这样,在以后每次发送信息给对应的客户端的时候,都会先在map中查询一下(通过ID查询):
_chatDialogMap.value(ID, NULL);
如果查询到了,则说明已经创建了界面,直接将这个界面信息返回return chatDialog;
,然后直接在这个界面显示聊天信息即可chatDialog->setChatList(chatData);
。