• QTcpSocket网络通讯多客户端功能


    首先声明此文章为学习Qt的网络通讯找的例子,仅供学习用,以下为自己总结,原作者的连接如下:GitHub - manfredipist/QTcpSocket: A simple Qt client-server TCP architecture to transfer data between peersA simple Qt client-server TCP architecture to transfer data between peers - GitHub - manfredipist/QTcpSocket: A simple Qt client-server TCP architecture to transfer data between peershttps://github.com/manfredipist/QTcpSocket

    解决的问题:

    在学习网络通讯时,Qt给你封装好了QTcpSocket类,来进行网络套接字通讯,经常会有需求进行一对多的功能,一台服务器,对多台客户端的开发,应用到实践中


    如何实现:

    实现分为:1、客户端 Client

                      2、服务器端 Server

    约定的数据格式头

    fileType:attachment 、 message

    QString("fileType:message,fileName:null,fileSize:%1;").arg(str.size()).toUtf8()


    代码块解析:

    客户端 Client

    .h文件

    1. //1:读数据
    2. void readSocket();
    3. //2:断开连接
    4. void discardSocket();
    5. //3:错误连接
    6. void displayError(QAbstractSocket::SocketError socketError);
    7. //4:发送数据
    8. void sendMessage();

    .cpp文件

    1. //1:连接
    2. socket->connectToHost(QHostAddress::LocalHost,8080);
    3. //2:读取数据在readyRead槽下
    4. void MainWindow::readSocket()
    5. {
    6. QByteArray buffer;
    7. QDataStream socketStream(socket);
    8. socketStream.setVersion(QDataStream::Qt_5_7);
    9. socketStream.startTransaction();
    10. socketStream >> buffer;
    11. QString header = buffer.mid(0,128);
    12. QString fileType = header.split(",")[0].split(":")[1];
    13. buffer = buffer.mid(128);
    14. if(fileType=="attachment"){
    15. //TODO
    16. }else if(fileType=="message"){
    17. //TODO
    18. QString message = QString("%1 :: %2").arg(socket->socketDescriptor()).arg(QString::fromStdString(buffer.toStdString()));
    19. }
    20. }
    21. //3:发送数据
    22. void Mainindow::sendMessage()
    23. {
    24. //1:组装数据
    25. QString str = ui->lineEdit_message->text();
    26. QDataStream socketStream(socket);
    27. socketStream.setVersion(QDataStream::Qt_5_7);
    28. QByteArray header;
    29. header.prepend(QString("fileType:message,fileName:null,fileSize:%1;").arg(str.size()).toUtf8());
    30. header.resize(128);
    31. //2:发送数据的包封装方式
    32. QByteArray byteArray = str.toUtf8();
    33. byteArray.prepend(header);
    34. //3:数据发送
    35. socketStream << byteArray;
    36. }

    服务器端 Server

    1:监听端口

    1. m_server = new QTcpServer();
    2. m_server->listen(QHostAddress::Any, 8080)

    2:当有客户端client连接时,发出newConnection 信号,由于要进行多客户端功能,得把客户端给存起来

    1. void MainWindow::appendToSocketList(QTcpSocket* socket)
    2. {
    3. connection_set.insert(socket);
    4. connect(socket, &QTcpSocket::readyRead, this, &MainWindow::readSocket);
    5. connect(socket, &QTcpSocket::disconnected, this, &MainWindow::discardSocket);
    6. connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
    7. ui->comboBox_receiver->addItem(QString::number(socket->socketDescriptor()));
    8. displayMessage(QString("INFO :: Client with sockd:%1 has just entered the room").arg(socket->socketDescriptor()));
    9. }
    10. void MainWindow::newConnection()
    11. {
    12. while (m_server->hasPendingConnections())
    13. appendToSocketList(m_server->nextPendingConnection());
    14. }

    3:readSocket()功能与客户端client一致,唯一区别,打印的时候,带上了客户端连接的唯一标识:socket->socketDescriptor

    4:reinterpret_cast<>用法将sender()转换成socket对象

    reinterpret_cast与static_cast_云之舟_的博客-CSDN博客_reinterpret_cast

    5:分发消息的机制

    1. void MainWindow::sendMessage(QTcpSocket* socket)
    2. {
    3. if(socket)
    4. {
    5. if(socket->isOpen())
    6. {
    7. QString str = ui->lineEdit_message->text();
    8. QDataStream socketStream(socket);
    9. socketStream.setVersion(QDataStream::Qt_5_7);
    10. QByteArray header;
    11. header.prepend(QString("fileType:message,fileName:null,fileSize:%1;").arg(str.size()).toUtf8());
    12. header.resize(128);
    13. QByteArray byteArray = str.toUtf8();
    14. byteArray.prepend(header);
    15. socketStream.setVersion(QDataStream::Qt_5_7);
    16. socketStream << byteArray;
    17. }
    18. else
    19. QMessageBox::critical(this,"QTCPServer","Socket doesn't seem to be opened");
    20. }
    21. else
    22. QMessageBox::critical(this,"QTCPServer","Not connected");
    23. }
    24. void MainWindow::on_pushButton_sendMessage_clicked()
    25. {
    26. QString receiver = ui->comboBox_receiver->currentText();
    27. if(receiver=="Broadcast")
    28. {
    29. foreach (QTcpSocket* socket,connection_set)
    30. {
    31. sendMessage(socket);
    32. }
    33. }
    34. else
    35. {
    36. foreach (QTcpSocket* socket,connection_set)
    37. {
    38. if(socket->socketDescriptor() == receiver.toLongLong())
    39. {
    40. sendMessage(socket);
    41. break;
    42. }
    43. }
    44. }
    45. ui->lineEdit_message->clear();
    46. }

  • 相关阅读:
    Sentinel基本使用与源码分析
    优思学院:想成为质量工程师?了解质量工程师职责和能力是关键!
    node.js下载安装环境配置以及快速使用
    【C++编程能力提升】
    IPM 鸟瞰图公式转换与推导
    UE4 MVP 坐标转换
    【一起刷题】环形链表
    写完Numpy100道基础练习题后的错误总结和语法总结
    自制操作系统日志——第十五天
    【JAVA】值传递与引用传递
  • 原文地址:https://blog.csdn.net/u013351233/article/details/126779880