C++ 使用 QTcpSocket 和 QTcpServer 的 Qt 双向客户端服务器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8917461/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 19:19:12  来源:igfitidea点击:

Qt bidirectional client server using QTcpSocket and QTcpServer

c++qttcpclient-server

提问by PTBG

I am trying to implement a bidirectional client-server program, where clients and servers can pass serialized objects between one another. I am trying to do this using Qt (QTcpSocket and QTcpServer). I have implemented programs like this in java, but I can't figure out how to do it using Qt. I've checked out the fortune clientand fortune serverexamples...but from what I can see, the client is simply signaling the server, and the server sends it some data. I need for the client and server to send objects back and forth. I am not looking for a complete solution, all I am looking for is some guidance in the right direction.

我正在尝试实现一个双向的客户端-服务器程序,客户端和服务器可以在其中相互传递序列化对象。我正在尝试使用 Qt(QTcpSocket 和 QTcpServer)来做到这一点。我已经在 java 中实现了这样的程序,但是我不知道如何使用 Qt 来做到这一点。我已经检查了财富客户端财富服务器示例……但从我所见,客户端只是向服务器发送信号,服务器向它发送一些数据。我需要客户端和服务器来回发送对象。我不是在寻找一个完整的解决方案,我只是在寻找一些正确方向的指导。

I wrote some code, which accepts a connection, but does not accept the data.

我写了一些代码,它接受连接,但不接受数据。

SERVER

服务器

this class is the server; it should be accepting a connection and outputting the size of the buffer which is being sent. However it is outputting 0

这个类是服务器;它应该接受连接并输出正在发送的缓冲区的大小。但是它输出 0

#include "comms.h"

Comms::Comms(QString hostIP, quint16 hostPort)
{
    server = new QTcpServer(this);
    hostAddress.setAddress(hostIP);
    this->hostPort = hostPort;


}

void Comms::attemptConnection(){
    connect(server, SIGNAL(newConnection()), this, SLOT(connectionAccepted()));
    //socket = server->nextPendingConnection();
    server->listen(hostAddress,hostPort);
    //receivedData = socket->readAll();
}

void Comms::connectionAccepted(){
    qDebug()<<"Connected";
    socket = new QTcpSocket(server->nextPendingConnection());

    char* rec = new char[socket->readBufferSize()];
    qDebug()<<socket->readBufferSize();
}

CLIENT

客户

This class is the client. It should be sending the string 'hello'. It sends it successfully (to my knowledge)

这个类是客户端。它应该发送字符串“hello”。它成功发送(据我所知)

#include "toplevelcomms.h"
#include "stdio.h"

TopLevelComms::TopLevelComms(QString hostIP, quint16 hostPort)
{
    tcpSocket = new QTcpSocket();
    hostAddress.setAddress(hostIP);
    this->hostPort = hostPort;
}


void TopLevelComms::connect(){
    tcpSocket->connectToHost(hostAddress,hostPort,QIODevice::ReadWrite);
    //tcpSocket->waitForConnected(1);

    QString string = "Hello";
    QByteArray array;
    array.append(string);
    qDebug()<<tcpSocket->write(array);
}

Please tell me what I'm doing wrong, or tell me the general logic of establishing what I want in Qt.

请告诉我我做错了什么,或者告诉我在 Qt 中建立我想要的东西的一般逻辑。

采纳答案by Kamil Klimek

QTcpSocket is asynchronous by default, so when you call connectToHost and write in same context it won't be sent, as socket is not connected. You should change your "client" code:

QTcpSocket 默认是异步的,所以当你调用 connectToHost 并在相同的上下文中写入时,它不会被发送,因为套接字没有连接。您应该更改“客户端”代码:

void TopLevelComms::connect(){
    tcpSocket->connectToHost(hostAddress,hostPort,QIODevice::ReadWrite);
    if(tcpSocket->waitForConnected()) // putting 1 as parameter isn't reasonable, using default 3000ms value
    {
        QString string = "Hello";
        QByteArray array;
        array.append(string);
        qDebug()<<tcpSocket->write(array);
    }
    else
    {
        qDebug() << "couldn't connect";
    }
}

Note: you also didn't check if you're able to listen

注意:你也没有检查你是否能够听

void Comms::attemptConnection(){
    connect(server, SIGNAL(newConnection()), this, SLOT(connectionAccepted()));
    //socket = server->nextPendingConnection();

    if(server->listen(hostAddress,hostPort))
    {
        qDebug() << "Server listening";
    }
    else
    {
        qDebug() << "Couldn't listen to port" << server->serverPort() << ":" << server->errorString();
    }
    //receivedData = socket->readAll();
}

And last thing. Note that QTcpServer::nextPendingConnection() return QTcpSocket, so instead of taking that new connection you create new QTcpSocket with nextPendingConnection as parent

还有最后一件事。请注意,QTcpServer::nextPendingConnection() 返回 QTcpSocket,因此您不是使用该新连接而是创建新的 QTcpSocket,并将 nextPendingConnection 作为父级

void Comms::connectionAccepted(){
    qDebug()<<"Connected";
    // WRONG! it will use QTcpSocket::QTcpSocket(QObject * parent)
    //socket = new QTcpSocket(server->nextPendingConnection());
    // use simple asign
    socket = server->nextPendingConnection();
    // move reading to slot
    connect(socket, SIGNAL(readyRead()), this, SLOT(readSocket()));
}

now we will move reading to separate slot

现在我们将阅读移动到单独的插槽

void Comms::readSocket()
{
    // note that dynamic size array is incompatible with some compilers
    // we will use Qt data structure for that
    //char* rec = new char[socket->readBufferSize()];
    qDebug()<<socket->readBufferSize();
    // note that QByteArray can be casted to char * and const char *
    QByteArray data = socket->readAll();
}

I must admit, that it is a lot of errors as for such small code sample. You need to get some knowledge about TCP/IP connections. Those are streams and there is no warranty that whole data chunk will get to you at once

我必须承认,对于这么小的代码示例,错误很多。您需要了解一些有关 TCP/IP 连接的知识。这些是流,不能保证整个数据块会立即到达您的手中

回答by Chris

It looks like you have a timing issue. Since your client and server are different processes, there's no way you can guarantee that the entirety of TopLevelComms::connect()is being executed (along with the network data transfer) before your server's connectionAccepted()function tries to read from the socket.

看起来你有时间问题。由于您的客户端和服务器是不同的进程,因此您无法保证TopLevelComms::connect()在您的服务器connectionAccepted()功能尝试从套接字读取之前执行整个过程(以及网络数据传输)。

I suspect that if you take advantage of QTcpSocket's waitForReadyRead()function, you should have better luck:

我怀疑如果你利用 QTcpSocket 的waitForReadyRead()函数,你应该有更好的运气:

void Comms::connectionAccepted(){
    qDebug()<<"Connected";
    socket = new QTcpSocket(server->nextPendingConnection());

    if( socket->waitForReadyRead() ) {
        char* rec = new char[socket->readBufferSize()];
        qDebug()<<socket->readBufferSize();
    }
}