2016-05-04 18 views
1

Ich erstelle einen (sehr grundlegenden) MJPG Server, um Webcam-Daten in einem Browser anzuzeigen. Ich habe es teilweise bis jetzt geschafft.Fehler bei der Verwendung von QTcpSocket

Hier ist mein Code:

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(); 
} 

}

Das Problem -

Als ich dieses Programm ausführen, wird das erste Bild gezeigt. Danach wird der folgende Fehler kontinuierlich auf der App gedruckt -

QIODevice::write (QTcpSocket): device not open 

Es ist wie die Fassung sah wurde geschlossen, so habe ich die Steckdose neu initialisiert, wie dies - socket = server->nextPendingConnection();, obwohl die App einen Fehler mit diesem warf Code. Irgendwelche Hilfe, wie man das repariert?

EDIT -

habe ich versucht, die Lambda-Methode, und es hat gut funktioniert. Allerdings ich immer noch mit 2 Probleme -

  1. Die Bildgröße hat übermäßig gering (um 270x480 mit niedrigstem JPG Qualität)

  2. (WICHTIGER) Ich muss manuell die drücken Reload-Button im Browser, um das Bild neu zu laden, es wird nicht automatisch von einem Bild zum anderen gewechselt.

+0

Ich benutze QT seit einiger Zeit nicht als Tatsache, da [das Projekt, auf dem du deinen Code aufsetztest] (http: // stackoverflow.com/questions/33064955/how-to-create-a-http-mjpeg-Streaming-Server-mit-qtcp-server-Sockets/33096855? Noredirect = 1 # comment61611267_33096855), aber ich empfehle Ihnen, eine Verzögerung zwischen dem Senden der Frames zu verwenden (zB 'QThread :: usleep (500);'). Hauptgrund ist, dass diese Methode (Apropos "MJPEG" -Server zu der Zeit nicht sehr effektiv ist, wenn ich über Leistung spreche. In meinen Tests, als ich die Verzögerung zwischen dem Senden der Frames auf einen niedrigen Wert einstellte, blieb das Video bei einigen hängen –

Antwort

1

Hier ist der Code ich den MJPEG Streaming Server in my original Project zu öffnen verwendet behandeln. Vielleicht kann es Ihnen helfen, Ihr Problem herauszufinden.

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

Es sah aus wie die Buchse Rather

als Erraten geschlossen wurde, eine Verbindung zu den Fehlersignalen von TCPServer und TCPSocket zu wissen, wenn Fehler auftreten, oder wenn ein Client die Verbindung trennt.

Das Problem, das Sie haben, ist die while (1) Schleife. Qt ist ein event-driven-Framework, also wird Code in einer Endlosschleife auf dem Hauptthread verhindern, dass Ereignisse geliefert werden.

Anstatt der Endlosschleife, verbinden Sie mit QTcpSocket::readyRead Signal und behandeln die Daten, wenn der angeschlossene Steckplatz aufgerufen wird.

Qt demonstriert dies mit dem Beispielcode Fortune Server und Fortune Client.

Wenn Sie C++ 11 verwenden, Sie eine Verbindung mit einer Lambda-Funktion können Sie die readyRead, wie diese

void TcpServer::newConnection() 
{ 
    ... 

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

     // handle received data here 

    }); 

} 
+0

Ich habe versucht, Ihre Antwort, aber jetzt bekomme ich diesen Fehler - Unhandled Ausnahme bei 0x000000C039E24388 (ucrtbase.dll) in app.exe: Ein ungültiger Parameter wurde an eine Funktion übergeben, die ungültige Parameter berücksichtigt fatal.' – FadedCoder

+0

Bitte aktualisieren Sie Ihre Frage, um den Code zu zeigen, der den Fehler erzeugt. – TheDarkKnight

+0

Ich sehe das Update, aber der Code ist immer noch der gleiche. Um Ihnen mit diesem Fehler zu helfen, müssen wir den Code sehen, der es erzeugt. – TheDarkKnight