【问题标题】:Qt bidirectional client server using QTcpSocket and QTcpServer使用 QTcpSocket 和 QTcpServer 的 Qt 双向客户端服务器
【发布时间】:2012-02-13 14:30:59
【问题描述】:

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

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

服务器

这个类是服务器;它应该接受连接并输出正在发送的缓冲区的大小。但是它正在输出 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();
}

客户

这个类是客户端。它应该发送字符串'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);
}

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

【问题讨论】:

    标签: c++ qt tcp client-server


    【解决方案1】:

    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";
        }
    }
    

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

    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();
    }
    

    最后一件事。请注意,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()));
    }
    

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

    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();
    }
    

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

    【讨论】:

    • 非常感谢,我能够通过套接字发送数据。但是由于某种原因,我仍然得到 0 的缓冲区大小。知道为什么吗?
    • 来自文档“读取缓冲区大小为 0(默认值)意味着缓冲区没有大小限制,确保没有数据丢失”。因此,它没有说明实际内容。你应该使用socket-&gt;size() 或socket-&gt;bytesAvailable()
    【解决方案2】:

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

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

    void Comms::connectionAccepted(){
        qDebug()<<"Connected";
        socket = new QTcpSocket(server->nextPendingConnection());
    
        if( socket->waitForReadyRead() ) {
            char* rec = new char[socket->readBufferSize()];
            qDebug()<<socket->readBufferSize();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-26
      • 1970-01-01
      • 1970-01-01
      • 2018-08-07
      • 1970-01-01
      • 2011-06-20
      相关资源
      最近更新 更多