Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-58262

QWebSocket does not send all data on flush

    XMLWordPrintable

Details

    • Bug
    • Resolution: Invalid
    • P1: Critical
    • None
    • 5.7.0, 5.7.1
    • WebSockets
    • None
    • Ubuntu 16.04

    Description

      Since Qt 5.7.0 when flushing the websocket, not all data is sent.

      This can be tested with the sample project attached to this ticket.

      The project contains two parts:

      • a websocket server which just prints the length of the received data and waits a bit between to answer
      • a websocket client which can send a file to the server

      Running a client built with Qt 5.7.0 or 5.7.1 on a 13MB file, the server receives a little less than 5MB.
      When the client is built with Qt 5.6.2, the server receives the whole file.

      This seems related to this commit http://code.qt.io/cgit/qt/qtbase.git/commit/?id=aaab800e1651fc9f04d62a76eda9b8cafbbe14c0

      The server code:

      #include <QCoreApplication>
      #include <QWebSocketServer>
      #include <QWebSocket>
      #include <QThread>
      
      class Server : public QObject {
      public:
          Server() {
              mWebSocketServer = new QWebSocketServer("test", QWebSocketServer::NonSecureMode);
              connect(mWebSocketServer, &QWebSocketServer::newConnection, this, &Server::onNewConnection);
          }
      
          void listen() {
              mWebSocketServer->listen(QHostAddress::Any, 1234);
          }
      
          void onNewConnection() {
              mTotal = 0;
              QWebSocket* socket = mWebSocketServer->nextPendingConnection();
              connect(socket, &QWebSocket::binaryMessageReceived, this, &Server::onMessageReceived);
              connect(socket, &QWebSocket::disconnected, this, &Server::onDisconnected);
              qDebug() << "New connection";
          }
      
          void onMessageReceived(const QByteArray& msg) {
              mTotal += msg.length();
              qDebug() << msg.length() << mTotal;
              QThread::msleep(100);
          }
      
          void onDisconnected() {
              qDebug() << "Disconnected";
          }
      
      private:
          QWebSocketServer* mWebSocketServer;
          qint64 mTotal = 0;
      };
      
      int main(int argc, char *argv[]) {
          QCoreApplication a(argc, argv);
          Server server;
          server.listen();
          return a.exec();
      }
      

      The client code:

      #include <QCoreApplication>
      #include <QWebSocket>
      #include <QFile>
      
      static constexpr int CHUNK_SIZE = 262168;
      
      class Client : public QObject {
      public:
          Client(QWebSocket* socket, const QString& fileName) :
                  mSocket(socket),
                  mFileName(fileName) {
              connect(mSocket, &QWebSocket::connected, this, &Client::onConnected);
              connect(mSocket, static_cast<void(QWebSocket::*)(QAbstractSocket::SocketError)>(&QWebSocket::error),
                      this, &Client::onError);
          }
      
      private:
          void onConnected() {
              QFile fp(mFileName);
              fp.open(QIODevice::ReadOnly);
              while (true) {
                  QByteArray data = fp.read(CHUNK_SIZE);
                  if (data.isEmpty()) {
                      break;
                  }
                  mSocket->sendBinaryMessage(data);
                  waitForDataToBeSent();
              }
              waitForDataToBeSent();
              QCoreApplication::instance()->quit();
          }
      
          void onError(QAbstractSocket::SocketError error) {
              qDebug() << "error" << error << mSocket->errorString();
          }
      
          void waitForDataToBeSent() {
              int flushCount = 0;
              do {
                  ++flushCount;
              } while (mSocket->flush());
      
              qDebug() << "flushCount" << flushCount;
          }
      
          QWebSocket* mSocket;
          QString mFileName;
      };
      
      int main(int argc, char *argv[]) {
          QCoreApplication a(argc, argv);
      
          QWebSocket socket;
          Client client(&socket, argv[1]);
          socket.open(QUrl("ws://localhost:1234"));
          return a.exec();
      }
      

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            kurt.pattyn Kurt Pattyn
            agateau Aurélien Gâteau
            Votes:
            2 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes