Sockets with QT - c++

How do I send data over sockets in C++ in QT ?
Here's my attempt, it does not work, regards
the server side that sends a file
void MainWindow::on_pushButton_clicked()
{
QString url("127.0.0.1");
sock.bind(QHostAddress(url), 1440);
sock.connectToHost("127.0.0.1", 1440);
sock.write("Coucou");
sock.close();
}
and the client that receives the file
void MainWindowClient::checker() {
csock.connectToHost("127.0.0.1", 1440);
char *datas;
sock.read(datas, 10000000);
ui->label->setText(datas);
csock.close();
}
When i run the program, it does not display "Coucou" as the label set on the client, why ?

Are you forced to use Sockets or can you use Websockets too? If so, Qt has a wonderful way to deal with Websockets and Signals / Slots.
For example, here's what I use for my Remote Control App on my smartphone to control my Music Player (the code has been truncated). But the server can also send commands to synchronize the UI on the smartphone.
The client:
RemoteClient::RemoteClient(CoverProvider *coverProvider, QObject *parent)
: QObject(parent)
, _socket(new QWebSocket("remote", QWebSocketProtocol::VersionLatest, this))
{
connect(_socket, &QWebSocket::textMessageReceived, this, &RemoteClient::processTextMessage);
}
/// Direction: Remote App is receiving orders from Server
void RemoteClient::processTextMessage(const QString &message)
{
if (message.isEmpty()) {
return;
}
QStringList list = message.split(QChar::Null);
if (list.size() <= 1) {
return;
}
int command = list.first().toInt();
switch (command) {
case CMD_Playback:
// Nothing
break;
case CMD_State: {
QMediaPlayer::State state = (QMediaPlayer::State) list.at(1).toInt();
if (state == QMediaPlayer::PlayingState) {
emit playing();
} else if (state == QMediaPlayer::PausedState) {
emit paused();
} else {
emit stopped();
}
break;
}
case CMD_Track:
/// etc.
break;
}
/// etc.
default:
break;
}
}
/// Direction: Remote App is sending orders to Server
void RemoteClient::setVolume(qreal v)
{
QStringList args = { QString::number(CMD_Volume), QString::number(v) };
_socket->sendTextMessage(args.join(QChar::Null));
}
The server:
void RemoteControl::startServer()
{
auto b = _webSocketServer->listen(QHostAddress::Any, _port);
qDebug() << Q_FUNC_INFO << b;
}
void RemoteControl::initializeConnection()
{
/// ...
connect(mediaPlayer(), &MediaPlayer::volumeChanged, this, &RemoteControl::sendVolume);
}
/// Direction: Server to updating Remote App
void RemoteControl::sendVolume(qreal volume)
{
QStringList args = { QString::number(CMD_Volume), QString::number(volume) };
_webSocket->sendTextMessage(args.join(QChar::Null));
}
/// Direction: Remote App is sending command to Server
void RemoteControl::decodeResponseFromClient(const QString &message)
{
if (message.isEmpty()) {
return;
}
QStringList args = message.split(QChar::Null);
if (args.count() < 2) {
return;
}
int command = args.first().toInt();
switch (command) {
case CMD_Volume: {
qreal volume = args.at(1).toFloat();
_currentView->mediaPlayerControl()->mediaPlayer()->setVolume(volume);
break;
}
/// etc.
}
}

Related

Pause Qt scene graph rendering based on Qt::ApplicationState

I'm trying to pause the rendering in a Qt app on android when put into background. After the initial state change, the app is stuck as no updates reach the connection.
QScopedPointer<QQuickWindow> window ...
QSemaphore renderSemaphore(1);
bool releaseOnRender {};
QObject::connect(window.data(), &QQuickWindow::beforeRendering,
qApp, [&] {
releaseOnRender = renderSemaphore.tryAcquire(1, -1);
}, Qt::DirectConnection);
QObject::connect(window.data(), &QQuickWindow::afterRendering,
qApp, [&] {
if (releaseOnRender) {
renderSemaphore.release(1);
}
}, Qt::DirectConnection);
Qt::ApplicationState prevApplicationState = Qt::ApplicationState::ApplicationActive;
QObject::connect(qApp, &QGuiApplication::applicationStateChanged,
qApp, [&] (Qt::ApplicationState state) {
qDebug() << "Changed state to" << state;
if (state != prevApplicationState) {
if (state == Qt::ApplicationState::ApplicationSuspended) {
renderSemaphore.acquire(1);
qDebug() << "Freezing render";
} else {
renderSemaphore.release(1);
qDebug() << "Releasing render";
}
prevApplicationState = state;
}
}, Qt::DirectConnection);
My implementation stems from the suggestion for a related question.
Is there any chance to achieve this? Perhaps using a different approach?

Qt Gui Thread is blocking Issue

I'm junior programmer
recently, I have implemented grabbing of Image using Halcon library.
when I press live button, Timer start to grab image. it works but main screen freezes to the timer cycle.
so, I am improving performance grabbing of Image using Thread
first I implemented thread like this
[ImageUpdateWorker.h]
class ImageUpdateWorker : public QObject
{
Q_OBJECT
public:
explicit ImageUpdateWorker(QObject* parent = 0, QString strThreadName = "ImageUpdateWorker");
~ImageUpdateWorker();
signals:
void finished();
void grab();
public slots:
void run();
private:
bool m_bStop{ false };
};
[ImageUpdateWorker.cpp]
ImageUpdateWorker::ImageUpdateWorker(QObject* parent, QString strThreadName)
: QObject(parent)
{
setObjectName(strThreadName);
}
ImageUpdateWorker::~ImageUpdateWorker()
{
}
void ImageUpdateWorker::run()
{
while (m_bStop == false)
{
emit grab();
}
emit finished();
}
second I implemented inherited QWidget UI Widget with output Screen like this
m_pThread = new QThread();
m_pUpdateWorker = new ImageUpdateWorker(nullptr, strName);
m_pUpdateWorker->moveToThread(m_pThread); // UpdateWorker move to Thread
connect(m_pThread, SIGNAL(started()), m_pUpdateWorker, SLOT(run()));
connect(m_pThread, SIGNAL(finished()), m_pThread, SLOT(deleteLater()));
connect(m_pUpdateWorker, SIGNAL(finished()), m_pThread, SLOT(quit()));
connect(m_pUpdateWorker, SIGNAL(finished()), m_pUpdateWorker, SLOT(deleteLater()));
connect(m_pUpdateWorker, SIGNAL(grab()), this, SLOT(onGrab()));
when I call "m_pThread->start();" screen starts to blokcing :(
If you have any advice or information, I would appreciate it. thank you for reading.
Use m_pImageUpdateThread->moveToThread(m_pThread);
I don't know in QT.
I sent you the code I used in C#.
Mainly you must use the delegates if you don't want to freeze the GUI.
hdisplay is the object HalconDotNet:HWindowControlWPF.
camera is a class where I define the camera parameters.
inside camera.Grab there is the code:
HOperatorSet.GrabImage(out ho_Image, _AcqHandle);
h_Image = new HImage(ho_Image);
At the initialization there is the code:
// Initialise the delegate
updateLiveDelegate = new UpdateLiveDelegate(this.UpdateLive);
HImage ho_Image = new HImage();
Here the code I use:
// ==================
// LIVE
// ==================
bool stopLive = true;
// Declare the thread
private Thread liveThread = null;
// Declare a delegate used to communicate with the UI thread
private delegate void UpdateLiveDelegate();
private UpdateLiveDelegate updateLiveDelegate = null;
private void btnLive_Click(object sender, RoutedEventArgs e)
{
try
{
stopLive = !stopLive;
// if stopLive = false, live camera is activated
if (!stopLive)
{
// Launch the thread
liveThread = new Thread(new ThreadStart(Live));
liveThread.Start();
}
}
catch (Exception ex)
{
// Error
}
}
private void Live()
{
try
{
while (stopLive == false)
{
if (camera.Grab(out ho_Image))
{
// Show progress
Dispatcher.Invoke(this.updateLiveDelegate);
}
else
{
// No grab
stopLive = true;
}
}
// here stopLive is true
}
catch (Exception ex)
{
// Error
}
}
private void UpdateLive()
{
try
{
int imageHeight;
int imageWidth;
string imageType;
ho_Image.GetImagePointer1(out imageType, out imageWidth, out imageHeight);
hDisplay.HalconWindow.SetPart(0, 0, imageHeight - 1, imageWidth - 1);
// display
hDisplay.HalconWindow.DispImage(ho_Image);
}
catch (Exception ex)
{
// Error
}
}

Alternative to `wxProcess::IsInputAvailable`

According to the documentation, the method wxProcess::IsInputAvailable "allows writing simple (and extremely inefficient) polling-based code waiting for a better mechanism in future wxWidgets versions." It also points to an example code dated to "15.01.00", I've checked on GitHub that the usage of this method dates back some 16 years or more.
Well, is this method of pooling still inefficient? Is there any better alternative?
I'm debugging an issue with a process's output not being read using something similar to the exec sample, and either way my application is sensitive to the timeliness of this polling and extracting of output.
I don't think the methods for reading the redirected output or the child process are inefficient. I think the document is stating that polling on the GUI thread as in the sample will be inefficient since it involves repeatedly generating pseudo idle events.
A possible alternative is to use a secondary thread to do the reading. Here is an example of using the lame mp3 encoder to encode a wav file:
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include <wx/filename.h>
#include <wx/filepicker.h>
#include <wx/msgqueue.h>
#include <wx/thread.h>
#include <wx/process.h>
const char* pathToLame = "d:\\temp\\lame.exe";
wxDEFINE_EVENT(wxEVT_THREAD_STDIN, wxThreadEvent);
wxDEFINE_EVENT(wxEVT_THREAD_STDERR, wxThreadEvent);
class LameThread : public wxThread
{
public:
enum ThreadMessage
{
ProcessComplete,
ExitThread,
MessageLast
};
LameThread(wxEvtHandler*, wxProcess*, wxMessageQueue<ThreadMessage>& q);
~LameThread();
private:
ExitCode Entry() wxOVERRIDE;
void DrainInput();
wxMessageQueue<ThreadMessage>& m_queue;
wxEvtHandler* m_handler;
wxProcess* m_process;
char* m_buffer;
size_t m_bufferSize;
};
LameThread::LameThread(wxEvtHandler* h, wxProcess* p,
wxMessageQueue<ThreadMessage>& q)
:wxThread(wxTHREAD_JOINABLE),m_queue(q)
{
m_process = p;
m_handler = h;
m_bufferSize = 1024*1024;
m_buffer = new char[m_bufferSize];
}
LameThread::~LameThread()
{
delete[] m_buffer;
delete m_process;
}
wxThread::ExitCode LameThread::Entry()
{
ExitCode c;
while ( 1 )
{
// Check if termination was requested.
if ( TestDestroy() )
{
wxProcess::Kill(m_process->GetPid());
c = reinterpret_cast<ExitCode>(1);
break;
}
ThreadMessage m = MessageLast;
wxMessageQueueError e = m_queue.ReceiveTimeout(10, m);
// Check if a message was received or we timed out.
if ( e == wxMSGQUEUE_NO_ERROR )
{
if ( m == ProcessComplete )
{
DrainInput();
c = reinterpret_cast<ExitCode>(0);
break;
}
else if ( m == ExitThread )
{
wxProcess::Kill(m_process->GetPid());
c = reinterpret_cast<ExitCode>(1);
break;
}
}
else if ( e == wxMSGQUEUE_TIMEOUT )
{
DrainInput();
}
}
return c;
}
void LameThread::DrainInput()
{
if ( !m_process->IsInputOpened() )
{
return;
}
wxString fromInputStream, fromErrorStream;
wxInputStream* stream;
while ( m_process->IsInputAvailable() )
{
stream = m_process->GetInputStream();
stream->Read(m_buffer, m_bufferSize);
fromInputStream << wxString(m_buffer, stream->LastRead());
}
while ( m_process->IsErrorAvailable() )
{
stream = m_process->GetErrorStream();
stream->Read(m_buffer, m_bufferSize);
fromErrorStream << wxString(m_buffer, stream->LastRead());
}
if ( !fromInputStream.IsEmpty() )
{
wxThreadEvent* event = new wxThreadEvent(wxEVT_THREAD_STDIN);
event->SetString(fromInputStream);
m_handler->QueueEvent(event);
}
if ( !fromErrorStream.IsEmpty() )
{
wxThreadEvent* event = new wxThreadEvent(wxEVT_THREAD_STDERR);
event->SetString(fromErrorStream);
m_handler->QueueEvent(event);
}
}
class MyFrame: public wxFrame
{
public:
MyFrame();
private:
void OnClose(wxCloseEvent& event);
void OnEncode(wxCommandEvent& event);
void OnProcessComplete(wxProcessEvent& event);
void OnThreadInput(wxThreadEvent&);
wxThread* m_lameThread;
wxMessageQueue<LameThread::ThreadMessage> m_msgQueue;
wxFilePickerCtrl* m_filePicker;
wxTextCtrl* m_textCtrl;
wxButton* m_encodeButton;
};
MyFrame::MyFrame()
:wxFrame(NULL, wxID_ANY, "Encode", wxDefaultPosition, wxSize(600, 400))
{
m_lameThread = NULL;
wxPanel* panel = new wxPanel(this, wxID_ANY);
m_filePicker = new wxFilePickerCtrl(panel, wxID_ANY, wxEmptyString,
"Select a file", "*.wav");
m_textCtrl = new wxTextCtrl(panel, wxID_ANY, wxEmptyString,
wxDefaultPosition, wxDefaultSize,
wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY);
m_encodeButton = new wxButton( panel, wxID_ANY, "Encode");
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(m_filePicker, wxSizerFlags().Expand().Border(wxALL) );
sizer->Add(m_textCtrl,
wxSizerFlags(1).Expand().Border(wxLEFT|wxRIGHT|wxBOTTOM));
sizer->Add(m_encodeButton,
wxSizerFlags().Border(wxLEFT|wxRIGHT|wxBOTTOM).Right());
panel->SetSizer( sizer );
panel->Layout();
m_encodeButton->Bind(wxEVT_BUTTON, &MyFrame::OnEncode, this);
Bind(wxEVT_CLOSE_WINDOW, &MyFrame::OnClose, this);
Bind(wxEVT_END_PROCESS, &MyFrame::OnProcessComplete, this);
Bind(wxEVT_THREAD_STDIN, &MyFrame::OnThreadInput, this);
Bind(wxEVT_THREAD_STDERR, &MyFrame::OnThreadInput, this);
}
void MyFrame::OnClose(wxCloseEvent& event)
{
if ( m_lameThread && m_lameThread->IsRunning() )
{
m_msgQueue.Post(LameThread::ExitThread);
m_lameThread->Wait();
delete m_lameThread;
}
Destroy();
}
void MyFrame::OnEncode(wxCommandEvent& event)
{
// Make sure the input file exists and is a wav file.
wxString file = m_filePicker->GetPath();
if ( !wxFileName::FileExists(file) )
{
m_textCtrl->AppendText("file does not exist.\n");
return;
}
wxFileName fn(file);
if ( fn.GetExt() != "wav" )
{
m_textCtrl->AppendText("File is not a wav file.\n");
return;
}
// Create a process and and encoder thread.
wxProcess* process = new wxProcess(this);
process->Redirect();
m_msgQueue.Clear();
m_lameThread = new LameThread(this, process, m_msgQueue);
m_lameThread->Run();
if ( !m_lameThread->IsRunning() )
{
m_textCtrl->AppendText("Unable to launch encoder thread.\n");
delete m_lameThread;
return;
}
// Execute the encoder command.
wxString cmd = pathToLame;
cmd << " \"" << fn.GetFullPath() << "\" \"";
cmd << fn.GetPathWithSep() << fn.GetName() << ".mp3\"";
wxExecute(cmd, wxEXEC_ASYNC, process);
m_encodeButton->Disable();
}
void MyFrame::OnProcessComplete(wxProcessEvent& event)
{
if ( m_lameThread && m_lameThread->IsRunning() )
{
m_msgQueue.Post(LameThread::ProcessComplete);
m_lameThread->Wait();
delete m_lameThread;
m_lameThread = NULL;
m_encodeButton->Enable();
}
}
void MyFrame::OnThreadInput(wxThreadEvent& event)
{
m_textCtrl->AppendText(event.GetString());
}
class MyApp : public wxApp
{
public:
virtual bool OnInit()
{
::wxInitAllImageHandlers();
MyFrame* frame = new MyFrame();
frame->Show();
return true;
}
};
wxIMPLEMENT_APP(MyApp);
On windows, this looks like this:
The basic idea is to run a tight loop in the thread's Entry method. In each iteration the thread waits for a message from a message queue, and if no message is received the thread tries to check the process for input or error messages.
That's essentially the same polling technique as used in the sample, but since it's in a secondary thread it won't clog the gui thread with idle events. If you need to do any processing of the input, that will also be done on the secondary thread.
If you're having trouble with timings, you can reduce the time spent waiting on the message queue.
Note that launching the secondary procss and receiving the event when it finishes can only be done on the main thread.
Finally I should mention that I'm not 100% sure this is completely thread safe. I wish there was a way to protect the reads and writes with the input and error streams with a mutex or critcal section; but since all the writing to those streams is done under the hood, I can't see any way to do that from user code. I can say I've used this technique on both windows and linux in the past without issue.

QWebSocketServer still connecting

I'm writing a simple server that pass some data to javascript by QWebSocketServer (basicly the same as qt doc...).
And, please take a look at here:
void DebuggerServer::onNewConnection() {
puts("C");
QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
connect(pSocket, &QWebSocket::textMessageReceived, this, &DebuggerServer::processMessage);
connect(pSocket, &QWebSocket::disconnected, this, &DebuggerServer::socketDisconnected);
printf("onNewConnection");
m_clients << pSocket;
}
I try to puts("C"); here, but I get nothing.
In my browser (latest version of chrome), If I send a request to the server, i will get some information like socket is connecting.
I've tried these things: closing firewall, changing port, changing browser, changing compile mode.
I'm not sure if this involve this issue, I'm compiling these code by msvc15 and manully moc headers.
This code is inject into other application by loadlibrary.
Full source code for the server is followed...
Server.cpp
#include "Server.h"
#include "Inspector.h"
#include "Server.moc"
#include <QtCore/QCoreApplication>
const int port = 5642;
DebuggerServer *server;
void StartServer() {
server = new DebuggerServer(port);
}
QT_USE_NAMESPACE
DebuggerServer::DebuggerServer(quint16 port, QObject *parent) :
QObject(parent),
m_pWebSocketServer(Q_NULLPTR),
m_clients()
{
m_pWebSocketServer = new QWebSocketServer(QStringLiteral("mvInspector"),
QWebSocketServer::NonSecureMode,
this);
puts("A");
if (m_pWebSocketServer->listen(QHostAddress::Any, port))
{
puts("B");
connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
this, &DebuggerServer::onNewConnection);
}
}
DebuggerServer::~DebuggerServer() {
m_pWebSocketServer->close();
qDeleteAll(m_clients.begin(), m_clients.end());
}
template<class T>
QString toStr(QList<T> y) {
QString rst;
for (T x : y)
rst += "\n" + QString(x);
return rst;
}
#define ASSERT_N(x) if (frame.length() != x) rst = "ERRON, wrong number of arguments."; else
void DebuggerServer::processMessage(QString message) {
QWebSocket *pSender = qobject_cast<QWebSocket *>(sender());
QStringList frame = message.split("\n");
QString rst;
rst += frame[0];
if (frame[0] == "getRootWindows") {
ASSERT_N(1)
rst += toStr(getRootWindows());
}
if (frame[0] == "getChildren") {
ASSERT_N(2)
rst += toStr(getChildren(frame[1].toInt()));
}
if (frame[0] == "getPropertyName") {
ASSERT_N(2)
rst += toStr(getPropertyName(frame[1].toInt()));
}
if (frame[0] == "getProperty") {
ASSERT_N(3)
rst += getProperty(frame[1].toInt(), frame[2].toStdString().c_str()).toBase64();
}
if (frame[0] == "getClassname") {
ASSERT_N(2)
rst += getClassname(frame[1].toInt());
}
if (frame[0] == "getClassname") {
ASSERT_N(2)
rst += getObjectname(frame[1].toInt());
}
printf(rst.toStdString().c_str());
pSender->sendTextMessage(rst);
}
void DebuggerServer::socketDisconnected()
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
if (pClient) {
m_clients.removeAll(pClient);
pClient->deleteLater();
}
printf("socketDisconnected");
}
void DebuggerServer::onNewConnection() {
puts("C");
QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
connect(pSocket, &QWebSocket::textMessageReceived, this, &DebuggerServer::processMessage);
connect(pSocket, &QWebSocket::disconnected, this, &DebuggerServer::socketDisconnected);
printf("onNewConnection");
m_clients << pSocket;
}
Server.h
#pragma once
#include <QtCore/qobject.h>
#include <QtWebSockets/qwebsocketserver>
#include <QtWebSockets/QWebSocket>
void StartServer();
class DebuggerServer : public QObject {
Q_OBJECT
public:
explicit DebuggerServer(quint16 port, QObject *parent = Q_NULLPTR);
virtual ~DebuggerServer();
private Q_SLOTS:
void onNewConnection();
void processMessage(QString message);
void socketDisconnected();
private:
QWebSocketServer *m_pWebSocketServer;
QList<QWebSocket *> m_clients;
};
DLLMain
#include <Windows.h>
#include "../Server.h"
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
StartServer();
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
Finally, it seems to be a bug of Qt 5.4.1 at least on windows 10 (msvc) .
I can make two Qt application connecting by the websocket, but cannot let At application connecting with a normal browser.
So, I use another websocket library and repect the original Qt websocket.

QThread wiringPi GPIO

I use a RaspberryPi and Qt for my Qt for my embedded Project
I have read about QThread. I tested QThread and it is working very fine.
I want to control some GPIO pins in my Thread, but this doesn't work
My GPIO pins are working, I have tested it.
Here my Code:
class referenz_thread:public QThread
{
Q_OBJECT
public:
bool x_isRef;
bool y_isRef;
void run()
{
x_isRef = false;
y_isRef = false;
digitalWrite(x_treiber,1);
digitalWrite(y_treiber,1);
digitalWrite(x_richtung,0);
digitalWrite(y_richtung,1);
while(1)
{
if(digitalRead(x_end) == 0)
{
digitalWrite(x_treiber,0);
x_isRef = true;
}
if(digitalRead(y_end) == 0)
{
digitalWrite(y_treiber,0);
y_isRef = true;
}
if((x_isRef == true) && (y_isRef == true))
{
break;
}
digitalWrite(x_v,1);
digitalWrite(y_v,1);
delay(1);
digitalWrite(x_v,0);
delay(1);
digitalWrite(x_v,1);
delay(1);
digitalWrite(x_v,0);
digitalWrite(y_v,0);
delay(1);
}
}
public slots:
};
This is in MainWindow.cpp
referenz_thread *ref_thread = new referenz_thread();
connect(ui->btn_ref,SIGNAL(clicked()),ref_thread,SLOT(start()));
I have wiringPiSetup already executed in my MainThread.