QTcpSocket网络通讯多客户端功能

这篇博客介绍了如何使用Qt的QTcpSocket类实现一个简单的TCP客户端和服务器,以进行一对多的网络通信。客户端和服务器分别通过QTcpSocket进行连接和监听,数据包以特定格式传输,包括消息类型和文件大小等信息。在服务器端,当有新的客户端连接时,会将其存储并处理多个客户端的连接。同时,详细展示了客户端和服务器端的代码实现,包括连接、读取、发送数据和错误处理等关键功能。
摘要由CSDN通过智能技术生成

首先声明此文章为学习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:读数据
void readSocket();
//2:断开连接
void discardSocket();
//3:错误连接
void displayError(QAbstractSocket::SocketError socketError);
//4:发送数据
void sendMessage();

.cpp文件

//1:连接
socket->connectToHost(QHostAddress::LocalHost,8080);

//2:读取数据在readyRead槽下
void MainWindow::readSocket()
{
    QByteArray buffer;

    QDataStream socketStream(socket);
    socketStream.setVersion(QDataStream::Qt_5_7);

    socketStream.startTransaction();
    socketStream >> buffer;

    QString header = buffer.mid(0,128);
    QString fileType = header.split(",")[0].split(":")[1];

    buffer = buffer.mid(128);
    if(fileType=="attachment"){
        //TODO
    }else if(fileType=="message"){
        //TODO
        QString message = QString("%1 :: %2").arg(socket->socketDescriptor()).arg(QString::fromStdString(buffer.toStdString()));
    }
}

//3:发送数据
void Mainindow::sendMessage()
{
    //1:组装数据
    QString str = ui->lineEdit_message->text();

    QDataStream socketStream(socket);
    socketStream.setVersion(QDataStream::Qt_5_7);

    QByteArray header;
    header.prepend(QString("fileType:message,fileName:null,fileSize:%1;").arg(str.size()).toUtf8());
    header.resize(128);
    //2:发送数据的包封装方式
    QByteArray byteArray = str.toUtf8();
    byteArray.prepend(header);
    //3:数据发送
    socketStream << byteArray;
}

服务器端 Server

1:监听端口

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

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

void MainWindow::appendToSocketList(QTcpSocket* socket)
{
    connection_set.insert(socket);
    connect(socket, &QTcpSocket::readyRead, this, &MainWindow::readSocket);
    connect(socket, &QTcpSocket::disconnected, this, &MainWindow::discardSocket);
    connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
    ui->comboBox_receiver->addItem(QString::number(socket->socketDescriptor()));
    displayMessage(QString("INFO :: Client with sockd:%1 has just entered the room").arg(socket->socketDescriptor()));
}

void MainWindow::newConnection()
{
    while (m_server->hasPendingConnections())
        appendToSocketList(m_server->nextPendingConnection());
}

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

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

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

5:分发消息的机制

void MainWindow::sendMessage(QTcpSocket* socket)
{
    if(socket)
    {
        if(socket->isOpen())
        {
            QString str = ui->lineEdit_message->text();

            QDataStream socketStream(socket);
            socketStream.setVersion(QDataStream::Qt_5_7);

            QByteArray header;
            header.prepend(QString("fileType:message,fileName:null,fileSize:%1;").arg(str.size()).toUtf8());
            header.resize(128);

            QByteArray byteArray = str.toUtf8();
            byteArray.prepend(header);

            socketStream.setVersion(QDataStream::Qt_5_7);
            socketStream << byteArray;
        }
        else
            QMessageBox::critical(this,"QTCPServer","Socket doesn't seem to be opened");
    }
    else
        QMessageBox::critical(this,"QTCPServer","Not connected");
}


void MainWindow::on_pushButton_sendMessage_clicked()
{
    QString receiver = ui->comboBox_receiver->currentText();

    if(receiver=="Broadcast")
    {
        foreach (QTcpSocket* socket,connection_set)
        {
            sendMessage(socket);
        }
    }
    else
    {
        foreach (QTcpSocket* socket,connection_set)
        {
            if(socket->socketDescriptor() == receiver.toLongLong())
            {
                sendMessage(socket);
                break;
            }
        }
    }
    ui->lineEdit_message->clear();
}

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值