Dimitri Danilov Dimitri Danilov - 1 month ago 11
C++ Question

Why QTcpSocket doesn't write ? I need to flush it to make it send my data

I read in the documentation that to send a packet with QTcpSocket I can just use the

write
method.
But when I do it, my server doesn't receive it. I need to call
flush
or
waitForByteWritten
to send it.

TCPClient::TCPClient(Client *babel , const std::string &hostname, unsigned short port, QObject *parent) : QObject(parent), client(babel), hostName(hostname), port(port), is_connected(false)
{
this->tcpSocket = new QTcpSocket(this);
connect(this->tcpSocket, SIGNAL(readyRead()),this, SLOT(readMessage()));
connect(this->tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
connect(this->tcpSocket, SIGNAL(connected()), this, SLOT(connectReady()));
connect(this->tcpSocket, SIGNAL(disconnected()), this, SLOT(disconnectedReady()));

}

TCPClient::~TCPClient()
{

}

bool TCPClient::initiateService()
{
this->tcpSocket->connectToHost(this->hostName.c_str(), this->port);
this->tcpSocket->waitForConnected(5000);
}

void TCPClient::connectReady()
{
this->is_connected = true;
}

void TCPClient::disconnectedReady()
{

}


bool TCPClient::sendBabelPacket(Protocol::BabelPacket &packet)
{
if(this->tcpSocket->state() == QAbstractSocket::ConnectedState && is_connected)
{
std::cout << "writing ... size : " << sizeof(Protocol::BabelPacket) + packet.dataLength<<std::endl;
this->tcpSocket->write((const char *)&packet, sizeof(Protocol::BabelPacket) + packet.dataLength);
//this->tcpSocket->flush();
return true;
}
else
{
std::cout << "socket close" << std::endl;
return false;
}
}


void TCPClient::shutDown()
{
this->tcpSocket->abort();
}

void TCPClient::displayError(QAbstractSocket::SocketError socketError)
{

}

void TCPClient::readMessage()
{
char buffer[sizeof(Protocol::BabelPacket)];
this->tcpSocket->read(buffer, sizeof(Protocol::BabelPacket));
}


When I call
write
, it returns the right amount of bytes.

I use this class in a GUI context, in the same thread.

Answer

QTcpSocket is a buffered device, so data is not written directly, but into internal buffer. Documentation states:

Note: TCP sockets cannot be opened in QIODevice::Unbuffered mode.

Because of it you should call flush or waitForBytesWritten to be sure something is transferred.

There is the difference between them. flush writes as much as possible from the internal write buffer to the underlying network socket, without blocking. waitForBytesWritten blocks until at least one byte has been written on the socket and the bytesWritten() signal has been emitted.