A simple communicate c/s app using QtUdpSocket - c++

I am a beginner of Qt.I want to use QUdpSocket to write a server app without a GUI.I have writen the client GUI app and server GUI app.They work well.But the server without GUI doesn't work well.
I try to use a while(true) loop to make the app running ,because I think after the code 'return a.exec()' the app will stop.But my server app does't work.
Here is my code:
client with GUI:
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
socket=new QUdpSocket(this);
//click pushbutton send message to server
connect(this->ui->pushButton,SIGNAL(clicked()),this,SLOT(send()));
}
Widget::~Widget()
{
delete ui;
}
//send message
void Widget::send()
{
QByteArray msg="client2:hello world";
socket->writeDatagram(msg.data(),msg.size(),QHostAddress::LocalHost,6666);
}
The client app and server with GUI app can work well.But When I try to make a server app without GUI,I found server can not get the message from client.
And here is my server.cpp without GUI:
#include "server.h"
Server::Server(QObject *parent) : QObject(parent)
{
socket=new QUdpSocket(this);
array=new QByteArray();
socket->bind(QHostAddress::LocalHost,6666,QAbstractSocket::DontShareAddress);
socket->open(QIODevice::ReadWrite); //without this line, the app will show:
//'QIOBevice::read(QUdpSocket):device not open',but it still can get the message from client.
connect(socket,SIGNAL(readyRead()),this,SLOT(printMsg()));
}
void Server::printMsg()
{
if(socket->hasPendingDatagrams()) //I forgot this line before.
{
array->resize(socket->pendingDatagramSize());
socket->readDatagram(array->data(),array->size());
socket->readAll();
qDebug()<<"yesyesyes";
}
}
I try many times,I think the problem is in my main.cpp:
#include <QCoreApplication>
#include "server.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Server s;
return a.exec();//after a.exec(),the app is still working!!!
}
In a GUI app, if I don't close the windows, the server app will always run, and the SIGNAL and SLOT I can understand.But in a console app, it seems that the app end fast and can't get the message from client(can't display the message).

You should not have a while(true) in your main, otherwise, you are effectively just freezing your thread and Qt application. This is exactly what app.exec(); is for, it will return when your application is closed (more details here)
If your application (with or without GUI) closes after calling app.exec(), it is due to one of the following:
You are closing it manually, e.g. with qApp->quit();
You are forcing an exit, e.g. with exit(1);
A fatal error or exception prematurely ends your application

Related

Can not close serial port using boost asio

I am having an issue that it seems someone else has encountered but appears to be not asked here. I have a very simple application that right now just opens and closes a serial port using boost asio (just trying to do some simple debugging right now before building a larger application. The calls reside in a qt based gui. The serial communication right now is set up in the window constructor:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(getData()));
timer->start(1000);
std::string comm = "/dev/ttyUSB0";
boost::asio::io_service io;
port = std::shared_ptr<boost::asio::serial_port>(new boost::asio::serial_port(io, comm));
std::cout << "Port has been successfully opened..." << std::endl;
boost::asio::serial_port_base::baud_rate baud(19200);
port->set_option(baud);
std::cout << "Baud rate set to 19200..." << std::endl;
getData();
}
getData will contain calls to the serial port at regular intervals, but right now it just makes a request to populate a time stamp on the gui with the current time.
The port is closed in the destructor
MainWindow::~MainWindow()
{
if (port->is_open()) port->close();
delete ui;
}
When the gui is closed, the destructor is called, but the system just hangs at the port closing. It appears that it is getting stuck in boost's posix_mutex.hpp lock method.
I have seen another post about this (https://cpc110.blogspot.com/2017/03/boost-asio-can-not-close-serial-port.html), but it appears that there is no answer to that one. Does anyone have any thoughts on this?
I am using boost 1.58 and Qt 5.8 on Ubuntu 16.04 LTS.
The problem is probably (I'm pretty new to boost::asio myself) that your io_service is already destructed. Try to make it a member of your MainWindow class.

How does work setFeaturePermission member function in QWebEnginePage?

I'm using Qt5.5.0 and wanted to know how does QWebEnginePage::setFeaturePermission work?
In this scenario I wanted to grant the loaded page media audio video capture permission but it does not work:
#include <QtWebEngineWidgets>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QWebEngineView *view = new QWebEngineView();
view->page()->setUrl(QUrl("http://127.0.0.1:3333/index.html"));
view->page()->setFeaturePermission(view->page()->url(), QWebEnginePage::MediaAudioVideoCapture, QWebEnginePage::PermissionGrantedByUser);
view->page()->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true);
view->page()->settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
view->show();
return app.exec();
}
What's wrong with my code?
According to the official Qt documentation for QWebEnginePage::setFeaturePermission:
Note: Call this method on featurePermissionRequested() signal, as it
is meant to serve pending feature requests only. Setting feature
permissions ahead of a request has no effect.
So, it has effect only when a feature is requested, for example here is a part of basic Qt Widget Application where QWebEngineView is created in the main window constructor and the signal featurePermissionRequested of the page (QWebEnginePage) is connected to the appropriate slot:
// slot to handle permission request
void MainWindow::featurePermissionRequested(const QUrl & securityOrigin,
QWebEnginePage::Feature feature)
{
// print origin and feature
qDebug() << securityOrigin << feature;
// grant permission
view->page()->setFeaturePermission(view->page()->url(),
QWebEnginePage::MediaAudioCapture, QWebEnginePage::PermissionGrantedByUser);
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// store web view pointer as class the member QWebEngineView *view;
view = new QWebEngineView();
// add view widget to 'verticalLayout' added to UI in UI Design
ui->verticalLayout->addWidget(view);
// set view page
view->page()->setUrl(QUrl("https://some_audio_capturing_site"));
// connect page signal with 'this' object slot
connect(view->page(),
SIGNAL(featurePermissionRequested(const QUrl&, QWebEnginePage::Feature)),
SLOT(featurePermissionRequested(const QUrl&, QWebEnginePage::Feature)));
}
I tested this example on one of audio capturing Web sites. When that site requests permission for microphone access it can be seen by debug print that the slot is triggered. It prints the site URL and 2 corresponding to QWebEnginePage::MediaAudioCapture. Nothing happens if the permission is not granted. However, after calling setFeaturePermission in that slot everything works as expected. The Web site is able to capture audio.

Restoring or bringing to front Qt desktop application

I have made my app into a single instance app using the RunGuard code found on this SO question:
Qt: Best practice for a single instance app protection
What I'd like to do is when the user tries to start the application while there is one running is to bring the existing running application to the front, and if minimised, restore it.
In my Delphi Windows programming days I used to broadcast a Windows message from the new application before closing it. The existing app would receive this and restore itself and come to the front.
Is something like this possible with Qt on Windows and Linux platforms?
Did you have any specific trouble with QtSingleApplication? It should be sufficient for what you want and will enable you to send a message to the running application. You just need a slot to get that message and if it matches what you expect then you restore it.
http://doc.qt.digia.com/solutions/4/qtsingleapplication/qtsingleapplication-example-trivial.html
The logview object is also set as the application's activation window. Every time a message is received, the window will be raised and activated automatically.
For some reason setActivationWindow() and activateWindow() don't work for me. This is my workaround:
#include <QWidget>
#include <qtsingleapplication.h>
class Window : public QWidget
{
Q_OBJECT
public:
Window(QWidget *parent = 0) : QWidget(parent) {}
public slots:
void readMessage(const QString &str) { showNormal(); }
};
int main(int argc, char *argv[])
{
QtSingleApplication instance(argc, argv);
Window *window = new Window;
window->show();
QObject::connect(&instance, SIGNAL(messageReceived(const QString &)), window, SLOT(readMessage(const QString &)));
if (instance.sendMessage(""))
return 0;
return instance.exec();
}
#include "main.moc"
In common, it is not possible without IPC. QtSingleApplication provide such IPC, but you will get extra dependency from QtNetwork module. (As #svlasov answered)
First problem that you will have: you can't raise any window of application if this application is not foreground. There are solutions for Windows and OS X, how to force raising of windows.

QWebView always fails to load website

I am running QtCreator 3.2.0, based on Qt 5.3.1 on Windows 8.1.
It seems that no matter what website i am trying to load, the onLoadFinished slot always returns false. I tried to load websites with and without SSL, both failed.
When I tried to load local resources everything worked well. So i monitored my network with wireshark and my Qt application does not even send a request, i also checked the QUrl with QUrl::isValid(), tried to use QWebView::load() instead of QWebView::setUrl() and ran my application as Administrator. Nothing worked.
I can't find any errors in my code and i somewhat feel like this is a bug, but I'm not certain about that.
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->webView->page()->networkAccessManager(), SIGNAL(finished(QNetworkReply*)),
this, SLOT(errorcheck(QNetworkReply*)));
QUrl url("http://www.nasa.gov/");
ui->webView->setUrl(url);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_webView_loadFinished(bool arg1)
{
ui->label->setText(arg1 ? "success" : "failure");
}
void MainWindow::errorcheck(QNetworkReply* QNR) {
qDebug() << QNR->errorString();
}
The output is: "Host www.nasa.gov not found"
Try
connect(QWebView->page()->networkAccessManager(), SIGNAL(finished(QNetworkReply*)),
this, SLOT(errorcheck(QNetworkReply*)));
void MainWindow::errorcheck(QNetworkReply* QNR) {
qDebug()<<QNR->errorString;
}
And check if any error occure.

parallely run an application while it starts another application in c++

I am trying to write an application program that can start another application using c++ in linux . Starting another application is not the problem . The problem I am facing is, that the parent application pauses till the child application is closed. I want the parent application to run along with the child application so that more functionalities of the parent application can be used. How do i go about it?
It would help me a lot if somebody could give me an idea on this.
The application consists of two files main.cpp and a virtualbotmain.cpp. The part of the
virtualbotmain.cpp: #include <iostream>
#include <stdlib.h>
VirtualBotMain::VirtualBotMain(QWidget *parent) :
QWidget(parent),
ui(new Ui::VirtualBotMain)
{
ui->setupUi(this);
}
void VirtualBotMain::on_enterButton_clicked()
{
QString enterString = ui->enterEdit->text();
ui->convoText->append("User: " + enterString);
ui->enterEdit->setText("");
if(enterString=="word")
{
ui->convoText->append("Joe: done..!!");
system("gedit");
}
}
The main.cpp is :
#include <QtGui/QApplication>
#include "virtualbotmain.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
VirtualBotMain w;
w.show();
return a.exec();
}
This is a GUI application that can be used to just type in the application i am trying to open and the application will do it for me. So trying to open many applications one after the other is becoming a problem as the GUI application won't work untill i close the previously opened application.
If you're using a system call (or a similar way to invoke the shell), you can apply the same logic you'd apply in your terminal to start a process "in the background":
system("./myProgram &");
// ^
// run in background
Better alternatives include forking, though it really depends on your specific requirements, which we do not know.
#include <stddef.h>
#include <process.h>
int status = spawnl( P_NOWAIT, "myprog", "myprog", "ARG1", "ARG2", NULL );