QTcpSocket - try to send bunch of requests - c++

I am trying to send 2 request one by one at same time. My code is following (this is example code):
QTcpSocket client;
...
client->write(block);
client->write(block);
Problem is following. Server receives only first request. There is no second request. I sniffed using wireshark and see that there is no second request in tcp packets.
What must i do to send many requests via QTcpSocket one by one?
UPD: I inserted qDebug() << this->bytesAvailable() << "bytes"; to server in readyRead() and qDebug() << this->bytesToWrite(); after each client->write(block); in client. Also, I added this to client:
connect(this, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWritten(qint64)));
void Connection::bytesWritten(qint64 count)
{
qDebug() << count << "bytes written";
}
I send ORDER_STATUS_GET_LIST constant in first request and ORDER_GET_LIST in second. I added data output in server. I received first command.
There is output listing:
Client:
Sending ORDER_STATUS_GET_LIST
11 bytes to write
Sending ORDER_GET_LIST
68 bytes to write
68 bytes written
Server:
68 bytes
ORDER_STATUS_GET_LIST received

According to the documentation, you need to flush() the socket IF you don't return to the event loop between multiple writes.
The proper solution would be to buffer your blocks into, e.g., a QByteArray and send the buffer at once.
QTcpSocket client;
QByteArray buffer;
...
buffer << block;
buffer << block;
client->write(buffer);

I found solution myself. I think that somebody needs this too.
Solution is simple:
QTcpSocket client;
...
client->write(block);
client->flush();
client->write(block);
client->flush();
We need to flush qt socket buffer to net before fill it with another data.

Related

why I receive some empty data received from the serialPort?

I extracted the data from my sensor using these command lines:
QObject::connect(this->serialPort,SIGNAL(readyRead()),this,SLOT(pollSerialPort()));
QObject::connect(serialPort, &::QSerialPort::errorOccurred,this,&Imu::handleError);
QByteArray hexData = d.append(serialPort->readAll().toHex());
qDebug() << "Serial received " << hexData;
however, I do not receive the data every time
I have a lot of empty messages like this
Serial received "555541321e7ff3029f61da00000000ffff00d2fffa0cbe24b124b124b1007b13d00000f4d8"
Serial received ""
I used this command to receive the data every ms but it doesn't work
QObject::connect(this->serialPort, &QSerialPort::readyRead, this, this {QTimer::singleShot(5,this,&Imu::pollSerialPort);});
Any solution please ?
Instead of polling on a timer, connect QSerialPort::readyRead to a slot and inside the slot use QSerialPort::readAll() until QSerialPort::bytesAvailable() is 0.

receive whole data from qtcpsocket [duplicate]

I know that TCP guarantees that all packets will arrive. But can a packet be separated into 2 or more? I am using Qt with class QTcpSocket, and I want to know is ReadyRead() signal is emitted only when full packet arrives. Or in other words, is there any sense to send packet size in first bytes and then wait in loop until all bytes had arrived? Or I can just call socket->readAll() and I must get one full packet?
If a large amount of data is sent, the packet can arrive in separate parts. Alternatively, multiple messages can be received in one readyRead slot.
It's good practice to control this by setting the first byte(s) to the number of bytes that will be sent. Then, in readyRead, you read the first bytes and append the data to a buffer until the expected amount of data has been received.
In receiving data, this also means that if multiple messages are received in one call to readyRead(), you can know where the first message ends and the next one begins.
Here's an example of a client that receives data in a readyRead function()
void MyClass::readyRead()
{
// m_pConnection is a QTcpSocket
while(m_pConnection->bytesAvailable())
{
QByteArray buffer;
int dataSize;
m_pConnection->read((char*)&dataSize, sizeof(int));
buffer = m_pConnection->read(dataSize);
while(buffer.size() < dataSize) // only part of the message has been received
{
m_pConnection->waitForReadyRead(); // alternatively, store the buffer and wait for the next readyRead()
buffer.append(m_pConnection->read(dataSize - buffer.size())); // append the remaining bytes of the message
}
QString msg(buffer); // data in this case is JSON, so we can use a QString
emit Log(QString("\tMessage Received: %1").arg(msg));
// Do something with the message
ProcessMessage(msg);
}
}

Qt: Differenciate between messages received using readAll() [duplicate]

I know that TCP guarantees that all packets will arrive. But can a packet be separated into 2 or more? I am using Qt with class QTcpSocket, and I want to know is ReadyRead() signal is emitted only when full packet arrives. Or in other words, is there any sense to send packet size in first bytes and then wait in loop until all bytes had arrived? Or I can just call socket->readAll() and I must get one full packet?
If a large amount of data is sent, the packet can arrive in separate parts. Alternatively, multiple messages can be received in one readyRead slot.
It's good practice to control this by setting the first byte(s) to the number of bytes that will be sent. Then, in readyRead, you read the first bytes and append the data to a buffer until the expected amount of data has been received.
In receiving data, this also means that if multiple messages are received in one call to readyRead(), you can know where the first message ends and the next one begins.
Here's an example of a client that receives data in a readyRead function()
void MyClass::readyRead()
{
// m_pConnection is a QTcpSocket
while(m_pConnection->bytesAvailable())
{
QByteArray buffer;
int dataSize;
m_pConnection->read((char*)&dataSize, sizeof(int));
buffer = m_pConnection->read(dataSize);
while(buffer.size() < dataSize) // only part of the message has been received
{
m_pConnection->waitForReadyRead(); // alternatively, store the buffer and wait for the next readyRead()
buffer.append(m_pConnection->read(dataSize - buffer.size())); // append the remaining bytes of the message
}
QString msg(buffer); // data in this case is JSON, so we can use a QString
emit Log(QString("\tMessage Received: %1").arg(msg));
// Do something with the message
ProcessMessage(msg);
}
}

Broadcast large data with Qt sockets

I'm using QT. I need to broadcast data, so I try to use QUdpSocket. But data can be too big(after writeDatagram QUdpSocket::error returns DatagramTooLargeError). So I split data and call writeDatagram several times to the parts. But Received socket receive data only once, only first packet. Receive code is
connect(&m_socketReceiver, &QUdpSocket::readyRead, this, &LocalNetSharing::onDataRead);
void LocalNetSharing::onDataRead()
{
while (m_socketReceiver.hasPendingDatagrams())
{
QByteArray datagram;
datagram.resize(m_socketReceiver.pendingDatagramSize());
m_socketReceiver.readDatagram(datagram.data(), datagram.size());
//process data
}
}
From the Qt documentation about QUdpSocket Class :
Note: An incoming datagram should be read when you receive the
readyRead() signal, otherwise this signal will not be emitted for the
next datagram.
So it seems that you are not reading the entire datagram in each call of onDataRead.
You don't specify host and port in readDatagram. I am not sure if it is the reason but the correct form is :
while (m_socketReceiver.hasPendingDatagrams())
{
QByteArray datagram;
datagram.resize(m_socketReceiver.pendingDatagramSize());
m_socketReceiver.readDatagram(datagram.data(), datagram.size(), host, &port);
//process data
}

Boost ASIO async_read_some

I am having difficulties in implementing a simple TCP server. The following code is taken from boost::asio examples, "Http Server 1" to be precise.
void connection::start() {
socket_.async_read_some(
boost::asio::buffer(buffer_),
boost::bind(
&connection::handle_read, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}
void connection::handle_read(const boost::system::error_code& e, std::size_t bytes_transferred) {
if (!e && bytes_transferred) {
std::cout << " " << bytes_transferred <<"b" << std::endl;
data_.append(buffer_.data(), buffer_.data()+bytes_transferred);
//(1) what here?
socket_.async_read_some(
boost::asio::buffer(buffer_),
boost::bind(
&connection::handle_read, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}
else// if (e != boost::asio::error::operation_aborted)
{
std::cout << data_ << std::endl;
connection_manager_.stop(shared_from_this());
}
}
In the original code the buffer_ is big enough to keep the entire request. It's not what I need. I've changed the size to 32bytes.
The server compiles and listens at port 80 of localhost, so I try to connect to it via my web browser.
Now if the statement (1) is commented-out, then only the first 32bytes of the request are read and the connection hangs. Web browser keeps waiting for the response, the server does.. I dont know what.
If (1) is uncommented, then the entire request is read (and appeded to data_), but it never stops - I have to cancel the request in my browser and only then does the else { } part run - I see my request on stdout.
Question 1: How should I handle a large request?
Question 2: How should I cache the request (currently I append the buffer to a string)?
Question 3: How can I tell that the request is over? In HTTP there always is a response, so my web-browser keeps waiting for it and doesnt close the connection, but how can my server know that the request is over (and perhaps close it or reply some "200 OK")?
Suppose browser send you 1360 bytes of data, you say asio to read some data into your buffer that you say it only have 32 bytes.
then first time that you call it your handler will be called with 32 bytes start of data. here if you comment (1) then browser try to send rest of its data(actually browser already sent it and it is in the OS buffer that wait for you to peek it from there) and you are possibly blocked behind io_service::run for some miracle!!
if you uncomment (1) as you say your loop started, you read first block, then next and another and ... until the data that the browser sent finished, but after that when you say asio to read some more data it will wait for some more data that never come from the browser( since browser already sent its information and is waiting for your answer ) and when you cancel the request from the browser, it will close its socket and then your handler will be called whith an error that say I can't read more data, since the connection is closed.!!
but what you should do here to make it work is: you should learn HTTP format and thus know what is the data that your browser sent to you and provide a good answer for it and then your communication with the client will be proceeded. in this case end of buffer is \r\n\r\n and when you see it you shouldn't read any more data, you should process what you read till now and then send a response to the browser.