QTCPSOCTED信号插槽多线程
我正在尝试为我的应用程序编写多线程服务器。我遇到了同时将图像发送给客户的问题。 我决定编写一个单身人士类,该类将触发一个信号,该信号将框架进入插座并发送给客户。但是,当我编写Connect()时,它不起作用,或者会引发错误“无法在另一个线程中创建对象”的错误。 我尝试了movetothread()。 尝试过QT :: QueuedConnection,它没有解决问题。如果您可以建议如何通过qtcpsocket同时发送图片而无需广播,或者如何在qtcpsocket中调用插槽 - 那将很酷。
如果代码在某些地方无法理解,我深表歉意,我已经尝试以不同的方式解决此问题,并且并不总是清洁非工作选择。
好的。首先,我们在其构造函数中创建MainWindow,我们启动DataSender Server。在IncomingConnection中,我们获取套接字手柄并将其传递给从Qthread继承的处理程序。目前,我尝试在此处编写Connect(),更早,我还尝试在插座本身内注册一个连接。接下来,我们启动插座本身,它确实成功地连接到服务器。 通过按键盘键,称为Emittera信号,从理论上讲,该信号应触发插座中的插槽并将CV :: MAT或QPIXMAP传递给它们。
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();
}
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();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在您的
sockethandler :: run()
中,您正在创建一个对象(套接字)。假设
sockethandler
是qrunnable
根据此方法名称,因此由您的qthreadpool
以螺纹方式调用从我所看到的,这是您的插座,您正在线程中创建一个对象。
要解决这个问题,请使套接字成为您的
sockethandler
class编辑:
有另一件事引起了我的注意:您正在继承
qthread
。这通常会破坏事物或引起怪异的行为。如果您可以在不继承它的情况下可以执行此操作,那就更安全,因为如果您不触摸它,就不会破坏它,那可能是导致问题的原因。
为了在不继承它的情况下添加功能,我将其包装成某些可以实施所需的任何类别的类。
In your
SocketHandler::run()
, you are creating an object (the socket).It's probably safe to assume
SocketHandler
is aQRunnable
according to this methods name, and is therefore called in a threaded fashion by yourQThreadPool
Your error says you are creating an object in a thread, well, from what I can see, it's your socket.
To get around this, make the socket a member of your
SocketHandler
classEdit:
There's one other thing that got my attention: you're inheriting
QThread
.This usually breaks things or causes weird behavior. It's safer if you can do without inheriting it as you can't break it if you don't touch it, it might be what's causing the problem.
To add functionality to it without inheriting it, I would wrap it into some class that would implement whatever it is that's required.