使用QTcpSocket实现连续快速使用
Using QTcpSocket for continuous fast usage
我需要实现一个以 300 Hz(每秒 300 个样本)读取数据的客户端。使用 C 套接字时,一切正常,因为我需要 运行 一个连续的 while 循环来从服务器获取数据(这会阻止客户端处理其他任何事情)。
因此,我决定尝试迁移到 QTcpsocket,以便处理从其他 object 到客户端 object 的信号。但是当我连接 Qtcpsocket 并连接信号读取时
connect(socket,&QTcpSocket::readyRead, this, &client::handleReadyRead, Qt::ConnectionType::QueuedConnection);
这是我的经纪人 -
QByteArray b = socket->read(12);
int packetLength = (unsigned char)b[6] << CHAR_BIT;
packetLength |= (unsigned char)b[7];
b = socket->read(packetLength);
(我为每个数据包得到一个 12 字节长的 header)
现在我得到一个非常慢的客户端 - 它每秒处理大约 3 个样本......我已经检查了多少 bytesavailable()
returns,看起来数据正在套接字缓冲区中堆积.
我究竟做错了什么?我必须得到一个非常快速的客户,但我不确定我正在阅读的方式是最佳的。
有没有更有效的方法呢?
谢谢
您当前的 handleReadyRead
假设一个完整的数据包可供读取并且数据包边界被保留。 TCP 不是这样工作的——它只是一个字节流。
更好的方法可能是将数据累积到 QByteArray
中,并在数据包可用时从 QByteArray
中读取数据包。
所以,假设您的 client
class 有一个数据成员...
QByteArray m_data;
我希望逻辑类似于...
void handleReadyRead ()
{
/*
* Append all available data to m_data.
*/
m_data.append(socket->readAll());
/*
* Now work our way through m_data processing complete
* packets as we find them. At any given point offset
* is the total size of all complete packets (including
* headers) processed thus far.
*/
int offset = 0;
while (m_data.length() >= offset + 12) {
/*
* We have enough data for a header so read the packet length.
*/
int packetLength = (unsigned char)m_data[offset + 6] << CHAR_BIT;
packetLength |= (unsigned char)m_data[offset + 7];
/*
* Check to see if we have sufficient data for the packet
* body. If not then we're done for the time being.
*/
if (m_data.length() < offset + 12 + packetLength)
break;
/*
* There is enough data for the complete packet so read it.
* Note that the following will include the header data in the
* packet variable. If that's not desired then change it to...
*
* auto packet = m_data.mid(offset + 12, packetLength);
*/
auto packet = m_data.mid(offset, 12 + packetLength);
/*
* Do whatever you want with the packet.
*/
do_something_with_the_packet(packet);
/*
* Update the offset according to the amount of data read.
*/
offset += 12 + packetLength;
}
/*
* Finally, remove the data processed from the beginning of
* the QByteArray.
*/
if (offset)
m_data = m_data.right(data.size() - offset);
}
以上内容未经测试,但肯定与我过去使用的代码行一致。
我需要实现一个以 300 Hz(每秒 300 个样本)读取数据的客户端。使用 C 套接字时,一切正常,因为我需要 运行 一个连续的 while 循环来从服务器获取数据(这会阻止客户端处理其他任何事情)。 因此,我决定尝试迁移到 QTcpsocket,以便处理从其他 object 到客户端 object 的信号。但是当我连接 Qtcpsocket 并连接信号读取时
connect(socket,&QTcpSocket::readyRead, this, &client::handleReadyRead, Qt::ConnectionType::QueuedConnection);
这是我的经纪人 -
QByteArray b = socket->read(12);
int packetLength = (unsigned char)b[6] << CHAR_BIT;
packetLength |= (unsigned char)b[7];
b = socket->read(packetLength);
(我为每个数据包得到一个 12 字节长的 header)
现在我得到一个非常慢的客户端 - 它每秒处理大约 3 个样本......我已经检查了多少 bytesavailable()
returns,看起来数据正在套接字缓冲区中堆积.
我究竟做错了什么?我必须得到一个非常快速的客户,但我不确定我正在阅读的方式是最佳的。
有没有更有效的方法呢?
谢谢
您当前的 handleReadyRead
假设一个完整的数据包可供读取并且数据包边界被保留。 TCP 不是这样工作的——它只是一个字节流。
更好的方法可能是将数据累积到 QByteArray
中,并在数据包可用时从 QByteArray
中读取数据包。
所以,假设您的 client
class 有一个数据成员...
QByteArray m_data;
我希望逻辑类似于...
void handleReadyRead ()
{
/*
* Append all available data to m_data.
*/
m_data.append(socket->readAll());
/*
* Now work our way through m_data processing complete
* packets as we find them. At any given point offset
* is the total size of all complete packets (including
* headers) processed thus far.
*/
int offset = 0;
while (m_data.length() >= offset + 12) {
/*
* We have enough data for a header so read the packet length.
*/
int packetLength = (unsigned char)m_data[offset + 6] << CHAR_BIT;
packetLength |= (unsigned char)m_data[offset + 7];
/*
* Check to see if we have sufficient data for the packet
* body. If not then we're done for the time being.
*/
if (m_data.length() < offset + 12 + packetLength)
break;
/*
* There is enough data for the complete packet so read it.
* Note that the following will include the header data in the
* packet variable. If that's not desired then change it to...
*
* auto packet = m_data.mid(offset + 12, packetLength);
*/
auto packet = m_data.mid(offset, 12 + packetLength);
/*
* Do whatever you want with the packet.
*/
do_something_with_the_packet(packet);
/*
* Update the offset according to the amount of data read.
*/
offset += 12 + packetLength;
}
/*
* Finally, remove the data processed from the beginning of
* the QByteArray.
*/
if (offset)
m_data = m_data.right(data.size() - offset);
}
以上内容未经测试,但肯定与我过去使用的代码行一致。