• 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. }

  • 相关阅读:
    JSON.parse()和JSON.stringify()的使用
    【CSDN线上竞赛第六期竞赛 】参赛介绍
    论文解读(GMT)《Accurate Learning of Graph Representations with Graph Multiset Pooling》
    H3C路由器 basic NAT典型组网配置
    如何防止IP和账户关联?
    小孢子的神奇之旅-如何阅读MindSpore报错信息(2)
    vmware的Linux虚拟机创建新的卷组VG
    10.4作业
    JVM中JAVA对象和数组内存布局
    基于springboot敬老院管理系统毕业设计-附源码161551
  • 原文地址:https://blog.csdn.net/u013351233/article/details/126779880