Двунаправленный клиентский сервер Qt с использованием QTcpSocket и QTcpServer

Я пытаюсь реализовать двунаправленную программу клиент-сервер, где клиенты и серверы могут передавать сериализованные объекты друг другу. Я пытаюсь сделать это с помощью Qt (QTcpSocket и QTcpServer). Я реализовал такие программы на java, но я не могу понять, как это сделать с помощью Qt. Я проверил клиент удачи и сервер удачи примеры...но из того, что я вижу, клиент просто сигнализирует серверу, и сервер отправляет его некоторые данные. Мне нужно, чтобы клиент и сервер отправляли объекты туда и обратно. Я не ищу полного решения, все, что я ищу, это некоторое руководство в правильном направлении.

Я написал код, который принимает соединение, но не принимает данные.

сервер

этот класс является сервером; он должен принимать соединение и выводить размер буфера, который отправляется. Однако он выводит 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);
}

2 ответов


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 как родитель!--5-->

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. Это потоки, и нет никакой гарантии, что весь кусок данных попадет к вам сразу


похоже, у вас проблемы со временем. Поскольку ваш клиент и сервер-это разные процессы, вы не можете гарантировать, что вся TopLevelComms::connect() выполняется (вместе с передачей сетевых данных) передconnectionAccepted() функция пытается читать из сокета.

Я подозреваю, что если вы воспользуетесь QTcpSocket в waitForReadyRead() функция, вы должны иметь больше удачи:

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

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