#c #qt #sockets #server #qtwidgets
#c #qt #сокеты #сервер #qtwidgets
Вопрос:
У меня возникли проблемы с отправкой данных с сервера клиенту, использующему Qt. Всякий раз, когда я делаю это QTcpSocket::waitForBytesWritten()
после вызова QTcpSocket::write(...)
, он возвращает false.
Я пытался использовать bytesWritten
сигнал, но он никогда не передается, предположительно потому, что никакие данные не могут быть записаны, и никакие данные не принимаются на стороне клиента.
writeData
Метод — это то, что вызывается в MainWindow
классе, но чтобы попытаться сузить причину проблемы, я перенес запись данных клиенту в newConnection
метод.
Сообщение Connection received
выводится в окно вывода. Я отправляю строку Some random data
в newConnection
методе клиенту для целей тестирования, но клиент ее не получает (код для вывода полученных данных на стороне клиента находится внутри Character::readData()
метода).
Значение returnValue
переменной равно true, и код возвращается в результате вызова client->waitForBytesWritten(-1)
метода. client->errorString()
выдает Unknown error
, а затем печатается сообщение Bytes written
(хотя, очевидно, ничего не написано, но я просто использую его как сообщение о состоянии).
Server.cpp
#include "Server.h"
Server::Server(QObject *parent) : QObject(parent)
{
server = new QTcpServer(this);
qDebug() << connect(server, SIGNAL(newConnection()), SLOT(newConnection()));
qDebug() << connect(server, SIGNAL(bytesWritten()), SLOT(bytesWritten()));
qDebug() << "Listening:" << server->listen(QHostAddress::Any, 1451);
server->waitForNewConnection(-1);
}
void Server::newConnection()
{
qDebug("Connection received");
client = server->nextPendingConnection();
client->write("Some random datan");
bool returnValue = client->flush();
qDebug() << "Return value: " << returnValue;
qDebug() << client->waitForBytesWritten(-1);
qDebug() << "Error: " << client->errorString();
qDebug() << "Bytes written";
}
void Server::bytesWritten(qint64 bytes)
{
qDebug() << "Bytes written: " << QString::number(bytes);
}
void Server::writeData(std::string data)
{
QByteArray byteArray = QByteArray(data.c_str());
qDebug() << "Write data: " << QString::fromStdString(data);
client->write(byteArray);
}
Client.cpp
#include "Client.h"
#include "mainwindow.h"
Client::Client(QObject* parent) : QObject(parent)
{
socket = new QTcpSocket(this);
(void)QObject::connect(socket, SIGNAL(connected()), this, SLOT(connected()));
qDebug() << "Connect signal" << QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
}
bool Client::connectToHost(QString host)
{
socket->connectToHost(host, 1451);
socket->waitForConnected();
qDebug() << "Error: " << QString::number(socket->error() == QAbstractSocket::UnknownSocketError);
return true;
}
void Client::connected()
{
qDebug("Socket is connected");
qDebug() << QString::number(socket->state() == QAbstractSocket::ConnectedState);
}
void Client::readData()
{
qDebug("Read data");
QTcpSocket* sender = static_cast<QTcpSocket*>(QObject::sender());
QByteArray data = sender->readAll();
std::string character = data.toStdString();
qDebug() << "Character received: " << QString::fromStdString(character);
MainWindow::characterReceived(character);
}
Комментарии:
1. Вы пробовали удалить
client->flush()
вызов? В этом не должно быть необходимости, и это может означать запись всех данных, что означает, что приclient->waitForBytesWritten(-1)
вызове больше не нужно записывать данные (хотя я не уверен, чтоwaitForBytesWritten
делает в этом случае). Можете ли вы также показать выходные данные от клиента.2.Из документации
"Note: This function may fail randomly on Windows. Consider using the event loop and the bytesWritten() signal if your software will run on Windows."
.3. @G.M. Я удалил
client->flush()
вызов, и теперьwaitForBytesWritten
вызов возвращаетсяtrue
. Что касаетсяwaitForBytesWritten
вызова метода, я просто пробовал все, что мог, чтобы заставить это работать, даже если некоторые вещи могут показаться ненужными. Странно то, что сервер говоритConnection received
, но затем говоритError: Unknown error
в моей строке отладки. И клиент находится вConnectedState
соответствии с отладкой (он распечатывает1
, илиtrue
), но он выдаетUnknownSocketError