登录功能和公聊功能的实现
发布日期:2021-07-01 04:27:34 浏览次数:2 分类:技术文章

本文共 4316 字,大约阅读时间需要 14 分钟。

文章目录

1 登录功能和公聊功能的实现

1.1 分析

问题:

  • 如何设计客户端和服务端之间的消息交互流程?

消息类型主要分为如下两种:

  • 控制消息:

    • 与聊天内容无关,设计用户状态。
    • 连接、断开、踢人、禁言等。
  • 文本消息:

    • 与聊天内容相关,用户可见消息。
    • 公聊消息,私聊消息。

用户登录、注册流程:

在这里插入图片描述

服务端认证流程:

在这里插入图片描述
简化设计:
在这里插入图片描述
文本消息传输模型(公聊模式):
在这里插入图片描述
文本消息传输模型(私聊模式):
在这里插入图片描述

1.2 代码实现

为了能够正确解析多条一次性接收的数据,需要对onDataReady()函数进行修改:

在这里插入图片描述
在这里插入图片描述

客户端中修改:

MainWin.h:
在这里插入图片描述
MainWinSlot.cpp修改后如下:

#include "MainWin.h"#include 
#include
void MainWin::initMember(){
m_client.setHandler(this); m_handlerMap.insert("CONN", CONN_Handler); m_handlerMap.insert("DSCN", DSCN_Handler); m_handlerMap.insert("LIOK", LIOK_Handler); m_handlerMap.insert("LIER", LIER_Handler); m_handlerMap.insert("MSGA", MSGA_Handler);}void MainWin::sendBtnClicked(){
QString text = inputGrpBx.title() + ":\n" + " " + inputEdit.text() + "\n"; TextMessage tm("MSGA", text); if( m_client.send(tm) ) {
inputEdit.clear(); }}void MainWin::logInOutBtnClicked(){
if( !m_client.isValid() ) {
if( loginDlg.exec() == QDialog::Accepted ) {
QString usr = loginDlg.getUser().trimmed(); QString pwd = loginDlg.getPwd(); if( m_client.connectTo("127.0.0.1", 8890) ) {
TextMessage tm("LGIN", usr + '\r' + pwd); m_client.send(tm); } else {
QMessageBox::critical(this, "失败", "连接不到远程服务端!"); } } } else {
m_client.close(); }}void MainWin::handle(QTcpSocket& obj, TextMessage& message){
if( m_handlerMap.contains(message.type()) ) {
MSGHandler handler = m_handlerMap.value(message.type()); (this->*handler)(obj, message); }}void MainWin::CONN_Handler(QTcpSocket&, TextMessage&){
}void MainWin::MSGA_Handler(QTcpSocket&, TextMessage& message){
msgEditor.appendPlainText(message.data());}void MainWin::DSCN_Handler(QTcpSocket&, TextMessage&){
setCtrlEnabled(false); inputGrpBx.setTitle("用户名");}void MainWin::LIOK_Handler(QTcpSocket&, TextMessage& message){
setCtrlEnabled(true); inputGrpBx.setTitle(message.data());}void MainWin::LIER_Handler(QTcpSocket&, TextMessage&){
QMessageBox::critical(this, "错误", "身份验证失败!"); m_client.close();}MainWin::~MainWin(){
m_client.close();}

服务端代码进行如下修改:

ServerHandler.h修改如下:
在这里插入图片描述
ServerHandler.cpp修改后的内容如下:

#include "ServerHandler.h"#include 
ServerHandler::ServerHandler(){
m_handlerMap.insert("CONN", CONN_Handler); m_handlerMap.insert("DSCN", DSCN_Handler); m_handlerMap.insert("LGIN", LGIN_Handler); m_handlerMap.insert("MSGA", MSGA_Handler);}void ServerHandler::handle(QTcpSocket& obj, TextMessage& message){
if( m_handlerMap.contains(message.type()) ) {
MSGHandler handler = m_handlerMap.value(message.type()); (this->*handler)(obj, message); }}void ServerHandler::CONN_Handler(QTcpSocket&, TextMessage&){
}void ServerHandler::DSCN_Handler(QTcpSocket& obj, TextMessage&){
for(int i=0; i
socket == &obj ) {
n->socket = NULL; break; } }}void ServerHandler::MSGA_Handler(QTcpSocket&, TextMessage& message){
const QByteArray& ba = message.serialize(); for(int i=0; i
socket != NULL ) {
n->socket->write(ba); } }}void ServerHandler::LGIN_Handler(QTcpSocket& obj, TextMessage& message){
QString data = message.data(); int index = data.indexOf('\r'); QString id = data.mid(0, index); QString pwd = data.mid(index + 1); QString result = ""; index = -1; for(int i=0; i
id ) {
index = i; break; } } if( index == -1 ) {
Node* newNode = new Node(); if( newNode != NULL ) {
newNode->id = id; newNode->pwd = pwd; newNode->socket = &obj; m_nodeList.append(newNode); result = "LIOK"; } else {
result = "LIER"; } } else {
Node* n = m_nodeList.at(index); if( pwd == n->pwd ) {
n->socket = &obj; result = "LIOK"; } else {
result = "LIER"; } } obj.write(TextMessage(result, id).serialize());}

参考资料:

转载地址:https://muzimin.blog.csdn.net/article/details/105795058 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:私聊模式的设计与实现
下一篇:解析扩展分区的数量

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月17日 22时19分32秒