2016-05-04 14 views
1

Я создаю (очень простой) сервер MJPG для отображения данных веб-камеры в браузере. Частично мне удалось это сделать.Ошибка при использовании QTcpSocket

Вот мой код:

TcpServer::TcpServer(QObject *parent) : 
QObject(parent) 
{ 
server = new QTcpServer(this); 
// whenever a user connects, it will emit signal 
connect(server, SIGNAL(newConnection()), 
    this, SLOT(newConnection())); 
if (!server->listen(QHostAddress::Any, 9999)) 
    qDebug() << "Server could not start"; 
else 
    qDebug() << "Server started!"; 
} 
... 
void TcpServer::newConnection() 
{ 
QTcpSocket *socket = server->nextPendingConnection(); 
QByteArray ContentType = ("HTTP/1.0 200 OK\r\n" \ 
    "Cache-Control: no-cache\r\n" \ 
    "Cache-Control: private\r\n" \ 
    "Content-Type: multipart/x-mixed-replace;boundary=--boundary\r\n"); 
socket->write(ContentType); 
std::vector<uchar> buff; 
Mat img; //OpenCV Material 
while (1) { 
    // Image to Byte Array via OPENCV Method 
    buff.clear();buff.empty(); 
    vCapture->read(img); //Read from webcam 

    imencode(".jpg", img, buff, compression_params); 
    std::string content(buff.begin(), buff.end()); 
    QByteArray CurrentImg(QByteArray::fromStdString(content)); 
    QByteArray BoundaryString = ("--boundary\r\n" \ 
     "Content-Type: image/jpeg\r\n" \ 
     "Content-Length: "); 
    BoundaryString.append(QString::number(CurrentImg.length())); 
    BoundaryString.append("\r\n\r\n"); 

    socket->write(BoundaryString); 
    socket->write(CurrentImg); // Write The Encoded Image 
    socket->flush(); 
} 

}

Проблема -

Когда я запускаю эту программу, то первое изображение будет показано. После этого следующая ошибка постоянно печатается на приложение -

QIODevice::write (QTcpSocket): device not open 

Похоже сокет был закрыт, поэтому я использовал повторно инициализировать сокет, как это - socket = server->nextPendingConnection();, хотя приложение бросил ошибку с этим код. Любая помощь в том, как это исправить?

EDIT -

Я попробовал метод лямбда и он работал отлично. Однако я до сих пор сталкиваются 2 проблемы -

  1. Размер изображения должен быть чрезмерно низкой (около 270x480 с самым низким качеством JPG)

  2. (ВАЖНЕЕ) я должен вручную нажмите перезагрузите кнопку в браузере, чтобы перезагрузить изображение, оно не меняется автоматически с одного изображения на другое.

+0

Не использовал QT в то время как факт, поскольку [Project вы основали свой код на] (http: // stackoverflow.com/questions/33064955/how-to-create-a-http-mjpeg-streaming-server-with-qtcp-server-sockets/33096855? noredirect = 1 # comment61611267_33096855), но я рекомендую вам использовать задержку между отправкой фреймов (например, 'QThread :: usleep (500);'). Основной причиной является то, что этот метод (говоря о сервере «MJPEG» в настоящее время не очень эффективен, когда речь идет о производительности. В моих тестах, когда я устанавливал задержку между отправкой кадров на низкое значение, видео всегда застряло на некоторых point –

ответ

1

Вот код, который я использовал, чтобы открыть сервер MJPEG Streaming в my original Project. Возможно, это поможет вам разобраться в вашей проблеме.

void MjpegStreamingEngine::StartServer(){ 

    m_TcpHttpServer = new QTcpServer(); 

    m_TcpHttpServer->connect(m_TcpHttpServer, 
          SIGNAL(newConnection()), 
          this, 
          SLOT(TcpHttpconnected())); 

    m_TcpHttpServer->listen(QHostAddress::Any, 
          8889); 
} 

void MjpegStreamingEngine::TcpHttpconnected(){ 

    m_TcpHttpClient = m_TcpHttpServer->nextPendingConnection(); 

    m_TcpHttpClient->connect(m_TcpHttpClient, 
          SIGNAL(readyRead()), 
          this, 
          SLOT(TcpHttpreadyRead())); 

} 

void MjpegStreamingEngine::TcpHttpreadyRead(){ 

    m_TcpHttpClient->readAll(); // Discard "Get Request String" 

    QByteArray ContentType = ("HTTP/1.0 200 OK\r\n" \ 
           "Server: en.code-bude.net example server\r\n" \ 
           "Cache-Control: no-cache\r\n" \ 
           "Cache-Control: private\r\n" \ 
           "Content-Type: multipart/x-mixed-replace;boundary=--boundary\r\n\r\n"); 

    m_TcpHttpClient->write(ContentType); 


    while(1){ 

     if (m_TcpHttpClient->isOpen()) 
     { 

      // Send Image 

      QThread::msleep(10); 

     }else{ 
      return; 
     } 

    } 

    m_TcpHttpClient->disconnect(); //Should never be Reached 
} 
2

Похоже сокет был закрыт

Вместо того, чтобы гадать, подключение к сигналам погрешности TCPServer и TCPSocket знать, когда происходят ошибки, или когда клиент разрывает соединение.

Проблема у вас есть while (1) петля. Qt представляет собой фреймворк event-driven, поэтому код в бесконечном цикле в основном потоке будет препятствовать доставке событий.

Вместо бесконечного цикла подключите сигнал QTcpSocket::readyRead и обработайте данные при вызове подключенного слота.

Qt демонстрирует это с помощью кода примера Fortune Server и Fortune Client.

Если вы используете C++ 11, вы можете использовать соединение с лямбда-функции для обработки readyRead, как этот

void TcpServer::newConnection() 
{ 
    ... 

    QTcpSocket *m_TcpHttpClient = server->nextPendingConnection(); 
    connect(m_TcpHttpClient, &QTcpSocket::readyRead, [=](){ 

     // handle received data here 

    }); 

} 
+0

Я пробовал ваш ответ, но теперь я получаю эту ошибку - «Необработанное исключение в 0x000000C039E24388 (ucrtbase.dll) в app.exe: недопустимый параметр передан функции, которая считает неверные параметры фатальными.« – FadedCoder

+0

вопрос, чтобы показать код, который вызывает ошибку. – TheDarkKnight

+0

Я вижу обновление, но код все тот же. Чтобы помочь вам с этой ошибкой, нам нужно увидеть код, который его производит. – TheDarkKnight