首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Qt套接字:如何连续发送请求并获得响应

Qt套接字:如何连续发送请求并获得响应
EN

Stack Overflow用户
提问于 2020-12-03 07:24:42
回答 1查看 621关注 0票数 0

我有一个QT客户端和服务器程序

服务器代码

main.cpp

代码语言:javascript
复制
#include <QCoreApplication>
#include "myserver.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    MyServer myserver;

    return a.exec();
}

myserver.cpp

代码语言:javascript
复制
#include "myserver.h"
#include <iostream>

MyServer::MyServer(QObject *parent)
{
    socket = new QUdpSocket(this);
    clientSocket = new QUdpSocket(this);
    socket->bind(QHostAddress::LocalHost,1234);
 
    connect(socket,SIGNAL(readyRead()),this,SLOT(processClientRequest()));
    qDebug()<<"=============================";
    qDebug()<<"     Server Started     ";
    qDebug()<<"=============================";
}

void MyServer::processClientRequest()
{
    qDebug()<<"processClientRequest()";
    QByteArray buffer;
    buffer.resize(socket->pendingDatagramSize());

    QHostAddress sender;
    quint16 senderPort;
    socket->readDatagram(buffer.data(),buffer.size(),&sender,&senderPort);
    qDebug()<<"Message:"<<buffer;
    
    std::string lineString = buffer.toStdString();

    double response = <some double value here>;//This value gets generated on the server using business some logic
    std::cout<<"response:"<<response<<endl;
    sendResponseDatagram(target);

}

void MyServer::sendResponseDatagram(double target)
{
    QString prefix="Response:";
    QString doubleStr = QString::number(target);
    QString word = prefix + doubleStr;
    QByteArray buffer;
    QHostAddress sender;
    buffer=word.toUtf8();
    clientSocket->writeDatagram(buffer.data(), QHostAddress::LocalHost, 5678 );
}

客户端代码

main.cpp

代码语言:javascript
复制
#include <QCoreApplication>
#include "myclient.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    MyClient client;

    const int len = 50;

    std::string lineArray[len];
    client.readFileIntoLineArray("MyInputFile.csv",lineArray);

    client.sendBulkArrayDataToServer(lineArray,len);
    qDebug()<<"Here";

    return a.exec();
}

myclient.cpp

代码语言:javascript
复制
#include "myclient.h"
#include <string>
#include <iostream>
#include <fstream>

using namespace std;

MyClient::MyClient(QObject *parent)
{
    mySocket = new QUdpSocket(this);
    serverSocket = new QUdpSocket(this);
    mySocket->bind(QHostAddress::LocalHost,5678);
    connect(mySocket,SIGNAL(readyRead()),this,SLOT(readDatagramsReceivedFromServer()));
}


void MyClient::sendBulkArrayDataToServer(std::string lineArray[],int length)
{
    for(int i=0;i<length;i++)
    {
        std::string line = lineArray[i];
        QString word=QString::fromStdString(line);
        QByteArray buffer;
        QHostAddress sender;
        buffer=word.toUtf8();
        serverSocket->writeDatagram(buffer.data(), QHostAddress::LocalHost, 1234 );
        qDebug()<<"Sent to server";//---->***BREAKPOINT#1***
    }
}

void MyClient::readFileIntoLineArray(std::string filepath,std::string lineArray[])
{
    int i=0;
    try
    {
        std::string line;
        ifstream file(filepath);

        if(file.is_open())
        {
            while(getline(file,line))
            {
                lineArray[i]=line;
                i++;

            }
            file.close();
        }
        else std::cout << "not able to open file";
    }
    catch (ifstream::failure e)
    {
        cout << e.what() << endl;
    }

}


void MyClient::readDatagramsReceivedFromServer()
{

    while (mySocket->hasPendingDatagrams()) {
        QByteArray buffer;
        buffer.resize(mySocket->pendingDatagramSize());
        QHostAddress sender;
        quint16 senderPort;
        mySocket->readDatagram(buffer.data(), buffer.size(),&sender, &senderPort);
        qDebug()<<"Received From Server:"<<buffer;//----->***BREAKPOINT#2***
    }
}
代码语言:javascript
复制
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Sent to server
Here
Received From Server: "Response:0.5"
Received From Server: "Response:2.7"
Received From Server: "Response:1.6"
Received From Server: "Response:0"
Received From Server: "Response:2.9"
Received From Server: "Response:3"
Received From Server: "Response:7"
Received From Server: "Response:2.6"
Received From Server: "Response:1"
Received From Server: "Response:2.1"
Received From Server: "Response:0"
Received From Server: "Response:1.6"
Received From Server: "Response:5"
Received From Server: "Response:4"
Received From Server: "Response:8"
Received From Server: "Response:9"
Received From Server: "Response:10"
Received From Server: "Response:11"
Received From Server: "Response:21"
Received From Server: "Response:3"

我原以为客户端控制台的输出应该如下所示

代码语言:javascript
复制
Sent to server
Received From Server: "Response:0.5"
Sent to server
Received From Server: "Response:2.7"
Sent to server
Received From Server: "Response:1.6"
Sent to server
Received From Server: "Response:0"
Sent to server
...
...
..

另外,如果我在调试模式下运行,并在BREAKPOINT#1上放置断点(请参见上文),我得到的全部信息是

代码语言:javascript
复制
Sent to server
Sent to server
Sent to server

如果我在BREAKPOINT#2上放置断点,控制台上就不会出现一个"Received From Server: ",所有发送的"Received From Server: "都会同时出现。所有这些都意味着所有发送请求都同时发生,然后接收到的信息发生在客户端。

我担心的是

  1. I应该能够为一个请求获得一个响应,否则,如果我的程序连续运行24或48小时并持续发送请求,客户端就不会得到一个响应!

  1. 也需要实时地映射每个响应与相应的请求,这是

无法实现的。

编辑下面()

即使我没有在循环中发送消息,而是单独发送消息,行为也是一样的。我修改了下面的代码

代码语言:javascript
复制
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    MyClient client;
    
    const int len = 50;
    
    std::string lineArray[len];
    client.readFileIntoLineArray("MyInputFile.csv",lineArray);
    //client.sendBulkArrayDataToServer(lineArray,len);
    client.sendOneSampleDataToServer(lineArray,1);
    client.sendOneSampleDataToServer(lineArray,2);//----->***BREAKPOINT#3***
    client.sendOneSampleDataToServer(lineArray,3);//----->***BREAKPOINT#4***
    qDebug()<<"Here";

    return a.exec();
}


void MyClient::sendOneSampleDataToServer(std::string lineArray[],int index)
{
        std::string line = lineArray[index];
        QString word=QString::fromStdString(line);
        QByteArray buffer;
        QHostAddress sender;
        buffer=word.toUtf8();
        serverSocket->writeDatagram(buffer.data(), QHostAddress::LocalHost, 1234 );
        qDebug()<<"Sent to server";

}

在BREAKPOINT#3和BREAKPOINT#4添加断点不会导致任何"Received From Server: "消息。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-03 08:12:22

核心应用程序是单线程的,您可以在同一个循环中发送所有消息。因此,即使您可能已经在中间接收到响应,Qt应用程序也只处理它们一次返回到事件循环(在exec()中)。因此,这是预期的,也是简单的。

当您希望在中间接收消息时,可以:

that.

  • Multi-thread

  • 将您的消息与QTimer一起发送,以便对它们进行空间设置,并在消息之间运行事件循环,但这并不是很复杂。

  • 在消息之间手动调用QEventLoop().processEvents();,但我并不特别推荐QTimer应用程序(QThread,QtConcurrent),但要正确处理并发性变得很棘手,只有在处理很重的情况下才值得。

如果您需要将每个请求映射到一个答案,我认为您需要在消息中添加一个ID (int)来标识它们。但是,如果您开始在一条消息中包含多个东西,我确实建议使用两端的QDataStream正确地序列化和反序列化您的数据,否则它会很快变得混乱和复杂。

一个好的方法通常是创建一个类来保存消息并序列化它们,例如:

代码语言:javascript
复制
class Message
{
public:
    explicit Message(int id, const QString& text);
    QByteArray toBinary();
    bool fromBinary(const QByteArray& binary);

private:
    int id;
    QString text;
}

QByteArray Message::toBinary()
{
    QByteArray binary;
    QDataStream stream(&binary, QIODevice::WriteOnly);
    // here: set endianness, precision & co for the stream
    stream << id;
    stream << text;
    return binary;
}

bool Message::fromBinary(const QByteArray& binary)
{
    QDataStream stream(binary);
    // here: set endianness, precision & co for the stream
    stream >> id;
    stream >> text;
    return (stream.status == QDataStream::Ok) && stream.atEnd();
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65121493

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档