c++ - example - Error al usar QTcpSocket
qtcpsocket server client example (2)
Estoy creando un servidor MJPG
(muy básico) para mostrar los datos de la cámara web en un navegador. En parte logré hacerlo hasta ahora.
Aquí está mi código:
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();
}
}
El problema -
Cuando ejecuto este programa, se muestra la primera imagen. Después de eso, el siguiente error se imprime continuamente en la aplicación:
QIODevice::write (QTcpSocket): device not open
Parecía que el socket se cerró, así que usé reinicializado el socket, así: socket = server->nextPendingConnection();
, aunque la aplicación arrojó un error con este código. ¿Alguna ayuda sobre cómo solucionar esto?
EDITAR -
Probé el método lambda y funcionó bien. Sin embargo, todavía tengo 2 problemas :
El tamaño de la imagen debe ser excesivamente bajo (alrededor de 270x480 con la calidad JPG más baja)
( MÁS IMPORTANTE ) Tengo que presionar manualmente el botón de recarga en el navegador para volver a cargar la imagen, no cambia automáticamente de una imagen a la otra.
Parecía que el socket se cerró
En lugar de adivinar, conéctese a las señales de error de TCPServer
y TCPSocket
para saber cuándo se producen errores o cuándo un cliente se desconecta.
El problema que tienes es el ciclo while (1) . Qt es un marco impulsado por eventos , por lo que tener código en un bucle infinito en el hilo principal evitará que se entreguen eventos.
En lugar del bucle infinito, conéctese a la señal QTcpSocket :: readyRead y maneje los datos cuando se llame a la ranura conectada.
Qt lo demuestra con el código de ejemplo de Fortune Server y Fortune Client .
Si está usando C ++ 11 , puede usar una conexión a una función lambda para manejar el readyRead
, como este
void TcpServer::newConnection()
{
...
QTcpSocket *m_TcpHttpClient = server->nextPendingConnection();
connect(m_TcpHttpClient, &QTcpSocket::readyRead, [=](){
// handle received data here
});
}
Aquí está el código que utilicé para abrir el servidor de transmisión MJPEG en mi proyecto original . Quizás puede ayudarte a descubrir tu problema.
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
}