【问题标题】:Network send problem网络发送问题
【发布时间】:2011-05-17 18:48:27
【问题描述】:

我尝试通过网络发送数据,但我编程的服务器没有收到数据。 此代码适用于:

void MainWindow::send()
{
 QByteArray qbarr;
 QDataStream qdstrm(&qbarr, QIODevice::WriteOnly);
 int iCount = qlist->count();
 QProgressDialog qprogrsdSend(QString("Sending..."), QString("Cancel"), 0, iCount, this);

 qdstrm.setVersion(QDataStream::Qt_4_6);

 qprogrsdSend.setWindowModality(Qt::WindowModal);

 for(int i = 0; i < iCount; i++)
 {
  if(qprogrsdSend.wasCanceled())
   break;

  qdstrm << (quint16)0;
  qdstrm << (*qlist)[i].data();
  qdstrm.device()->seek(0);
  qdstrm << (quint16)(qbarr.size() - sizeof(quint16));

  qprogrsdSend.setValue(i);

  qtcpsoClient->write(qbarr);
  qtcpsoClient->flush();
  qtcpsoClient->waitForBytesWritten();

  qbarr.clear();
 }

 qlblStatus2->setText("File is send.");
}

但是从 qlist 发送每个元素需要很多时间。现在我尝试修改方法,以便首先将 qlist 中的所有元素保存在 qbarr 中。而不是我发送文件。这是不起作用的代码:

void MainWindow::send()
{
 QByteArray qbarr;
 QDataStream qdstrm(&qbarr, QIODevice::WriteOnly);
 int iCount = qlist->count();
 QProgressDialog qprogrsdSend(QString("Sending..."), QString("Cancel"), 0, iCount, this);

 qdstrm.setVersion(QDataStream::Qt_4_6);

 qprogrsdSend.setWindowModality(Qt::WindowModal);

 qdstrm << (quint16)0;

 for(int i = 0; i < iCount; i++)
 {
  if(qprogrsdSend.wasCanceled())
   break;

  qdstrm << (*qlist)[i].data();

  qprogrsdSend.setValue(i);
 }

 qdstrm.device()->seek(0);
 qdstrm << (quint16)(qbarr.size() - sizeof(quint16));

 qtcpsoClient->write(qbarr);
 qtcpsoClient->flush();
 qtcpsoClient->waitForBytesWritten();

 qbarr.clear();

 qlblStatus2->setText("File is send.");
}

这是我用来读取数据的方法:

void QServerThread::onReadyRead(void)
{
 if(read == false)
 {
  read = true;
  emit reading(true);
 }

 while(!qtcpsoClient->atEnd())
 {
  QDataStream qdstrmIn(qtcpsoClient);
  QDataStream qdstrmOut(qfile);
  QByteArray qbarrData;
  quint16 qui16BlockSize = 0;
  int iVersion = qdstrmIn.version();

  qdstrmIn.setVersion(iVersion);
  qdstrmOut.setVersion(iVersion);

  if(qtcpsoClient->bytesAvailable() < (int)sizeof(quint16))
   break;

  qdstrmIn >> qui16BlockSize;

  if(qtcpsoClient->bytesAvailable() < qui16BlockSize)
   break;

  qdstrmIn >> qbarrData;

  qdstrmOut << qbarrData.data();

  qfile->flush();
 }

 read = false;
 emit reading(false);
}

我希望有人可以帮助我。 谢谢

保罗

【问题讨论】:

    标签: c++ qt4


    【解决方案1】:

    问题可能出在您的服务器上吗?我想您将 onReadyRead 连接到套接字的 readyRead 信号。每收到一块数据,该信号就会发出一次。因此,如果您一次发送所有数据,则信号可能只发出一次。我想qtcpsoClient 是套接字。现在,我可以看到这种情况发生了:

    你在这么多数据到达之前问bytesAvailable() &lt; somesize。在这种情况下,您读取了一个尺寸,但在那之后立即爆发,并且在下一次读取时您已经丢失了尺寸信息并读取了垃圾。

    在您发送多条短消息之前,这可能不是问题,并且在您询问数据大小之前,每条消息都设法完全到达。错误仍然存​​在。

    在旁注中。在您的原始客户端代码中 - 为什么您在每个 write 之后都 flush()waitForBytesWritten()?这可能是它如此缓慢的原因。

    [编辑:根据谢尔盖·塔切诺夫的评论更正]

    【讨论】:

    • “永不返回”部分并不完全正确。 onReadyRead() 将再次被调用,只是这次它会读取一些任意数据,而不是下一个块大小。那么行为是未定义的。否则,答案是正确的。
    • @Sergey 哦,所以每次bytesAvailable() 返回的值发生变化时都会发出readyRead?我想我总是预料到最坏的情况,所以我从来没有注意到这种行为。
    • 更准确地说,当一些数据到达输入缓冲区时,readyRead() 会被发出一次,并且只有一次,除了它永远不会递归发出。这实际上很有用,因为如果还没有足够的数据,您不必将任何内容读入临时缓冲区。也就是说,假设您知道确切多少就足够了。
    • 我从 Qt 文档的财富客户端示例中获取的两个 bytesAvailable() 请求。但我已经删除了那部分。 flush() 和 waitForBytesWritten() 仅用于 for 循环,因为 write() 方法只发送我的 send() 方法结束。
    • @Paul 所以 .. 它现在工作了吗?在Fortune Client 示例中使用bytesAvailable() 是正确的,因为如果您注意到如果没有足够的可用字节,它们会在循环中等待更多,而不是脱离。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    • 1970-01-01
    • 1970-01-01
    • 2015-06-02
    • 1970-01-01
    相关资源
    最近更新 更多