我正在编写一个客户端-服务器应用程序的原型,在战斗模式下,应用程序必须每秒传输大约 60 次 QString、QVariant 形式的 ~ 200 个值。
问题是,以这种在客户端发送的速度,我成功地收到了大约 50 个数据包中的一个,在其他情况下,从流中获取的变量结果是无效的 ( QVariant::invalid
)
服务器代码:
void TDummyWorker::initialize()
{
timer = new QTimer(this);
timer->setInterval(10);
connect(timer,SIGNAL(timeout()),this,SLOT(foo())); //будем посылать данные с заданным интервалом
timer->start();
server = new QTcpServer(this);
connect(server,&QTcpServer::newConnection,this,&TDummyWorker::somebodyConnected);
server->listen(QHostAddress::Any, 33333);
}
void TDummyWorker::foo()
{
QVector <TNamedVariable> vars;
static int n=0;
int ndata = 200;
for (int i=0; i<ndata; i++)
{
//формируем фейковые данные
vars.append(TNamedVariable("variable_number_" % QString::number(i), (i%2 != 0 ? float((i+n)*0.01) : int(i+n)) ));
}
for (QMap<int ,QTcpSocket *>::iterator it = clients.begin(); it!=clients.end(); ++it)
{
sendToClient(*it, vars); //посылаем данные всем подключенным клиентам
}
n++;
if (n>1000000) n=0;
}
void TDummyWorker::sendToClient(QTcpSocket *socket, QVector <TNamedVariable> &vars)
{
QByteArray arr;
QDataStream out(&arr, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_2);
int n=vars.size();
out << quint16(0);
for(int i=0; i<n;i++)
{
out << vars[i];
}
out.device()->seek(0);
out << quint16(arr.size() - sizeof(quint16));
sendMessage(vars[0].value.toString() % " " % QString::number(arr.size() - sizeof(quint16)));
socket->write(arr);
}
这就是我在客户端获取数据的方式:
void TClient::recieveData()
{
QDataStream stream(socket);
stream.setVersion(QDataStream::Qt_5_2);
QVector <TNamedVariable> vars;
quint16 nextBlockSize=0;
while (true)
{
if (nextBlockSize==0)
{
if (socket->bytesAvailable() < sizeof(quint16))
{
break;
}
stream >> nextBlockSize;
}
if (socket->bytesAvailable() < nextBlockSize)
break;
TNamedVariable buf;
while (!stream.atEnd())
{
stream >> buf;
buf.debug();
vars.append(buf);
}
nextBlockSize = 0;
}
emit sendData(vars);
}
如果我们每秒发送 1-2 个变量,那么客户端会正常接受所有内容,我增加传输频率和向量中变量的数量越多,我得到的损坏数据就越多。我怀疑这个错误是微不足道的,因为代码几乎完全来自教科书示例。
所有编辑后正确工作的代码:
void TClient::recieveData()
{
QDataStream stream(socket);
stream.setVersion(QDataStream::Qt_5_2);
static int nbad = 0;
TNamedVariable buf;
static quint16 nextBlockSize=0;
while (true)
{
if (nextBlockSize == 0)
{
if (socket->bytesAvailable() < sizeof(quint16))
{
break;
}
stream >> nextBlockSize;
}
if (socket->bytesAvailable() < nextBlockSize)
{
break;
}
while (!stream.atEnd())
{
stream >> buf;
if (!buf.value.isValid())
{
qDebug()<<"op :("<<++nbad;
}
if (buf.name == "eod")
break;
vars.append(buf);
}
if (buf.name == "eod")
{
emit sendData(vars);
vars.clear();
}
nextBlockSize = 0;
}
}