持久 Qt 本地套接字 IPC
我正在开发一个在本地服务器和客户端应用程序之间使用 IPC 的应用程序。它没有什么特别的,因为它的结构类似于 Qt 文档和示例。
问题在于客户端频繁发送数据包,并且与服务器本地套接字(NT 上的命名管道)的连接/断开速度非常慢。所以我想要实现的是两个应用程序之间的“持久”连接。
客户端应用程序连接到本地服务器(QLocalServer)没有任何问题:
void IRtsClientImpl::ConnectToServer(const QString& name)
{
connect(_socket, SIGNAL(connected()), this, SIGNAL(connected()));
_blockSize = 0;
_socket->abort();
_socket->connectToServer(name, QIODevice::ReadWrite);
}
并且也以传统的 Qt 方式发送请求:
void IRtsClientImpl::SendRequest( quint8 cmd, const QVariant* const param_array,
unsigned int cParams )
{
// Send data through socket
QByteArray hdr(PROTO_BLK_HEADER_PROJ);
QByteArray dataBlock;
QDataStream out(&dataBlock, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_5);
quint8 command = cmd;
out << blocksize_t(0) // block size
<< hdr // header
<< quint32(PROTO_VERSION_PROJ) // protocol version
<< command // command
<< cParams; // number of valid parameters
for (unsigned int i = 0; i < cParams; ++i)
out << param_array[i];
// Write the current block size
out.device()->seek(0);
out << dataBlock.size() - sizeof(blocksize_t);
_socket->write(dataBlock);
}
没有问题。但诀窍在于服务器端的readyRead() 信号。这是readyRead()处理槽的当前实现:
void IRtsServerImpl::onReadyRead()
{
QDataStream in(_lsock);
in.setVersion(QDataStream::Qt_4_5);
if (_blocksize == 0)
{
qDebug("Bytes Available on socket: %d", _lsock->bytesAvailable());
if (_lsock->bytesAvailable() < sizeof(blocksize_t))
return;
in >> _blocksize;
}
// We need more data?
if (_lsock->bytesAvailable() < _blocksize)
return;
ReadRequest(in);
// Reset
_blocksize = 0;
}
如果不将_blocksize
设置为零,我无法接收更多数据,只能接收第一个块组(我希望整个块在没有分段的情况下到达,因为这是通过管道,但事实并非如此,想想吧)。当然,我期望这种行为,因为 _blocksize 不再代表当前的流。好吧,重置 _blocksize 可以解决问题,但是如果没有在套接字上获得越来越多的字节数组,我就无法从客户端重新发送另一个数据包。我想要的是处理 ReadRequest 中的请求并接收下一个数据块,而不需要连接/重新连接所涉及的应用程序。
也许我应该“调节”传入数据的速率?
非常感谢。
I'm developing an application that uses IPC between a local server and a client application. There is nothing particular to it, as it's structured like the Qt documentation and examples.
The problem is that the client sends packets frequently and connecting/disconnecting from the server local socket (named pipe on NT) is very slow. So what I'm trying to achieve is a "persistent" connection between the two applications.
The client application connects to the local server (QLocalServer) without any problem:
void IRtsClientImpl::ConnectToServer(const QString& name)
{
connect(_socket, SIGNAL(connected()), this, SIGNAL(connected()));
_blockSize = 0;
_socket->abort();
_socket->connectToServer(name, QIODevice::ReadWrite);
}
And sends requests also in the traditional Qt manner:
void IRtsClientImpl::SendRequest( quint8 cmd, const QVariant* const param_array,
unsigned int cParams )
{
// Send data through socket
QByteArray hdr(PROTO_BLK_HEADER_PROJ);
QByteArray dataBlock;
QDataStream out(&dataBlock, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_5);
quint8 command = cmd;
out << blocksize_t(0) // block size
<< hdr // header
<< quint32(PROTO_VERSION_PROJ) // protocol version
<< command // command
<< cParams; // number of valid parameters
for (unsigned int i = 0; i < cParams; ++i)
out << param_array[i];
// Write the current block size
out.device()->seek(0);
out << dataBlock.size() - sizeof(blocksize_t);
_socket->write(dataBlock);
}
No problem. But the trick resides on the readyRead() signal in the server-side. Here's the current implementation of the readyRead() handling slot:
void IRtsServerImpl::onReadyRead()
{
QDataStream in(_lsock);
in.setVersion(QDataStream::Qt_4_5);
if (_blocksize == 0)
{
qDebug("Bytes Available on socket: %d", _lsock->bytesAvailable());
if (_lsock->bytesAvailable() < sizeof(blocksize_t))
return;
in >> _blocksize;
}
// We need more data?
if (_lsock->bytesAvailable() < _blocksize)
return;
ReadRequest(in);
// Reset
_blocksize = 0;
}
Without setting _blocksize
to zero I could not receive more data, only the first block group (I would expect an entire block to arrive without segmentation since this is through a pipe, but it does not, go figure). I expect that behavior, sure, since the _blocksize does not represent the current stream flow anymore. All right, resetting _blocksize does the trick, but I can't resend another packet from the client without getting an increasing array of bytes on the socket. What I want is to process the request in ReadRequest and receive the next data blocks without resorting to connecting/reconnecting the applications involved.
Maybe I should 'regulate' the rate of the incoming data?
Thank you very much.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论