I am trying to write a multithreaded server for my application. And I ran into the problem of sending the image to the clients at the same time. I decided to write a singleton class that will trigger a signal on which a frame will come to the sockets and be sent to the client. But when I write connect() it doesn't work or it throws an error "Unable to create an object in another thread". I have tried moveToThread(). Tried Qt::QueuedConnection, it didn't solve the problem. If you can suggest how to simultaneously send a picture by clients via QTcpSocket without broadcast or how to call a slot in QTcpSocket - that would be cool.
I apologize if the code is incomprehensible in some places, I have already tried to solve this problem in different ways and did not always clean non-working options.
OK. First we create the mainwindow in its constructor, we start the datasender server. In IncomingConnection we get the socket handle and pass it to the handler which is inherited from QThread. At the moment I'm trying to write connect () here, earlier I also tried to register a connection inside the socket itself. Next, we start the socket itself and it really successfully connects to the server. By pressing a keyboard key, the emittera signal is called, which, in theory, should trigger slots in sockets and pass cv::Mat or QPixmap to them.
emitter.cpp
#include "emitter.h"
emitter* emitter::em= nullptr;
emitter::emitter(QObject *parent):
QObject(parent)
{
}
void emitter::startEmit()
{
emit testEmit();
}
emitter *emitter::getInstance()
{
if(em == nullptr){
em = new emitter();
}
return em;
}
server.h
#include "datasender.h"
DataSender::DataSender(QObject *parent) :
QTcpServer(parent)
{
}
void DataSender::startServer()
{
if(this->listen(QHostAddress::Any, 8080))
{
qDebug() << "Server started";
}
else
{
qDebug() << "Server did not start!";
}
}
void DataSender::incomingConnection(qintptr handle)
{
SocketHandler *task = new SocketHandler(this);
connect(task, &QThread::finished, task, &QThread::deleteLater);
task->socketDescriptor = handle;
task->start();
qDebug() << "pool started";
}
sockethandler.cpp
#include "sockethandler.h"
SocketHandler::SocketHandler(QObject *parent):
QThread(parent)
{
}
void SocketHandler::run()
{
socket = new MySocket();
socket->setDescriptor(socketDescriptor);
connect(emitter::getInstance(), &emitter::testEmit, socket, &MySocket::NewData , Qt::QueuedConnection );
socket->EventLoop();
exec();
}
mysocket.cpp
#include "mysocket.h"
MySocket::MySocket(QObject *parent) :
QObject(parent)
{
qDebug() << "MySocket";
connect(&socket, &QTcpSocket::disconnected ,
this, &MySocket::disconnected);
connect(&socket, &QTcpSocket::connected,
this, &MySocket::connected);
connect(&socket, &QTcpSocket::readyRead,
this, &MySocket::readyRead);
connect(&socket, &QTcpSocket::bytesWritten,
this, &MySocket::bytesWritten);
}
void MySocket::setDescriptor(qintptr desk)
{
socket.setSocketDescriptor(desk);
Work = true;
}
void MySocket::connected()
{
}
void MySocket::disconnected()
{
Work = false;
}
void MySocket::readyRead()
{
}
void MySocket::bytesWritten(qint64 bytes)
{
qDebug() << "bytes written: " << bytes;
}
void MySocket::EventLoop()
{
if(socket.socketDescriptor()){
while(Work){
socket.waitForBytesWritten(500);
}
}
}
void MySocket::NewData()
{
qDebug() << "newData";
socket.write("Test");
}
mainwindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
em = emitter::getInstance();
datasender.startServer();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
gogogo();
}
void MainWindow::gogogo()
{
qDebug() << "Work";
em->startEmit();
}