QWebSocketServer still connecting - c++

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.

Related

How to check if keyboard is connected or or not and use it if it is connected during runtime?

So I have a QT project in which I want to check if a keyboard is connected. In case it's not connected I want to be able to still use it if it is connected during the program is running. I looked around and found a few libraries that might be suitable but I am not sure if they can do what I want. Libraries in question: libinput, libusb or Solid with KDE. My question is, will one of these libraries do what I want it to do or is it something completly different? If it is one of the above libraries than any examples would help a ton because I can't really get anything out of the documentation. I should probably also mention that I use a linux, or to be more exact openSUSE Leap 15.2
Okay, well turns out it wasn't as complicated as I thought and none of the libraries that I talked about are needed. Here is my solution, in case any one in the future is looking for something similar.
scanner.h
#ifndef SCANNER_H
#define SCANNER_H
#include <QObject>
#include <QThread>
#include <QTimer>
#include <QDebug>
#include <QString>
#include <QFile>
#include <QSocketNotifier>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
class Scanner : public QThread
{
Q_OBJECT
public:
static Scanner* getInstance(void);
int saveInCorrectFormat(int code);
protected:
void run() override;
signals:
void ChipScanned(QString rfid);
private slots:
void handleNotification(int socket);
void checkScannerData();
private:
Scanner(QObject *parent = 0);
~Scanner();
void initScanner(void);
static Scanner* sInstance;
QString defaultPath = "/dev/input/event2";
QString rfid;
QTimer* sCheckScanner;
QFile *sScannerFile;
QSocketNotifier *sNotifier;
int fd;
bool notificationEnabled;
struct input_event event;
int RFID[10];
int i = 0;
int buffer = 0;
};
#endif // SCANNER_H
scanner.cpp
#include "scanner.h"
Scanner* Scanner::sInstance = new Scanner();
Scanner* Scanner::getInstance(void){
return sInstance;
}
Scanner::Scanner(QObject *parent) : QThread(parent){
moveToThread(this);
start();
}
Scanner::~Scanner(){
}
void Scanner::run(){
initScanner();
QThread::exec();
}
/**
* #brief Scanner::initScanner
* initialize the timer to check up on the keyboard event file
*/
void Scanner::initScanner(void){
notificationEnabled = false;
sScannerFile = new QFile(defaultPath);
sCheckScanner = new QTimer(this);
sCheckScanner->setInterval(100);
sCheckScanner->setSingleShot(false);
connect(sCheckScanner, SIGNAL(timeout()), this, SLOT(checkScannerData()));
sCheckScanner->start();
}
/**
* #brief Scanner::checkScannerData
* check if the keyboard is connected or not
* if it is connected, activate event handling
*/
void Scanner::checkScannerData(){
if(sScannerFile->exists()){
if(notificationEnabled){
return;
}
fd = open(defaultPath.toUtf8().data(), O_RDONLY | O_NONBLOCK);
if(-1 != fd){
sNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
connect(sNotifier, SIGNAL(activated(int)), this, SLOT(handleNotification(int)));
qDebug() << "Scanner connected";
notificationEnabled = true;
}
}else{
if(notificationEnabled){
sNotifier->setEnabled(false);
disconnect(sNotifier, SIGNAL(activated(int)), this, SLOT(handleNotification(int)));
delete sNotifier;
close(fd);
qDebug() << "Scanner disconnect";
notificationEnabled = false;
}
}
}
/**
* #brief Scanner::handleNotification
* check if the keyboard is still connected or if the event was the disconnect
* if still connected than read the data and save it
* #param socket
*/
void Scanner::handleNotification(int socket){
if(!sScannerFile->exists()){
if(notificationEnabled){
sNotifier->setEnabled(false);
disconnect(sNotifier, SIGNAL(activated(int)), this, SLOT(handleNotification(int)));
delete sNotifier;
close(fd);
qDebug() << "Scanner disconnect";
notificationEnabled = false;
}
return;
}
if(read(fd, &event, sizeof(event)) == sizeof(event)){
if(event.type != EV_SYN){
if(event.value == 1 && event.code != 28){
RFID[i] = saveInCorrectFormat(event.code);
rfid.append(QString("%1").arg(saveInCorrectFormat(event.code)));
i++;
}
}
}
if(rfid.size() == 10){
buffer++;
if(buffer == 10){
emit ChipScanned(rfid);
qDebug() << rfid;
i = 0;
buffer = 0;
rfid.clear();
}
}
}
/**
* #brief Scanner::saveInCorrectFormat
* correct the raw data in the it's right format
* #param code
* current data to convert
* #return
* converted data
*/
int Scanner::saveInCorrectFormat(int code){
switch(code){
case 11:
return 0;
case 28:
return -1;
default:
return code-1;
}
}
A few extra infos:
My device isn't really a keyboard but the input is handled as if it is a keyboard that's why I have to make a few tweaks with the raw data before it is in the expected format. Anyone else most likely won't need those tweaks, like int saveInCorrectFormat or the if condition after reading the data. I believe this code is rather universal which means changing the defaultPath and making a few tweaks while reading the raw data will probably make it possible to use it for other devices as well.

Use QT to read from socket

I want to use IPC in order to exchange messages between two separate applications. The first one is a BASH script which is fired when a specific udev rule is activated (in Ubuntu Linux), and the other one is a simple Qt 5.7 console application, which acts as a server.
I already have the Qt server working and printing a message when it accepts a connection to the specified socket. What I'm trying to achieve now, is to make the server do something not when it accepts a connection, but when it receives a certain "message". Any ideas on how to do it?
Below is my code:
server.cpp
#include "server.h"
Server::Server() : QThread()
{
m_server = new QLocalServer(this);
m_server->listen("somesocket.sock");
connect(m_server, &QLocalServer::newConnection, this, &Server::testFunction);
}
Server::~Server()
{
m_server->removeServer("somesocket.sock");
}
void Server::run()
{
}
void Server::testFunction(){
qDebug() << "Sth happened!";
return;
}
server.h
#ifndef SERVER_H
#define SERVER_H
#include <QThread>
#include <QObject>
#include <QDebug>
#include <QLocalServer>
class Server : public QThread
{
public:
Server();
~Server();
void run();
void testFunction();
private:
QLocalServer *m_server;
signals:
void connectionEstablished(bool);
};
#endif // SERVER_H
You could connect to readyRead signal, and then check received message, like in this example:
connect( this, SIGNAL(readyRead()), SLOT(readClient()) );
void readClient()
{
QTextStream ts( this );
int line = 0;
while ( canReadLine() ) {
QString str = ts.readLine();
if(str == "someSpecialMessage")
{
//...
}
line++;
}
}
for more informations about this signal, see documentation: http://doc.qt.io/qt-5/qiodevice.html#readyRead
This is also an example of client and server applications in Qt, using QSocket and QServerSocket: https://doc.qt.io/archives/3.3/clientserver-example.html

Qt: create a library to connect to an external resource and use it in different applications

I am trying to implement a library to connect to an external resource and interact with it via an XML-based API. However I don't know how to get all the data before processing it. I am using QTcpSocket on Windows.
The way I have to interact with the resource is as follow:
Connect to the server
Send an XML message with credentials
Get the response from the server
Parse the XML response to extract the session ID
Send other requests in XML with the session ID in it and parse the XML responses.
Use the result in my application
Of course, depending on the request the message will not have the same structure so I need to parse the XML in the same function, right? And if so, how can I wait for all the data to arrive before parsing it?
Furthermore, as mentioned, it is under a Windows environment so I cannot use "waitForReadyRead" since as stated in the documentation:
This function may fail randomly on Windows. Consider using the event loop and the readyRead() signal if your software will run on Windows.
How does it work?
Thanks,
Fred
Edit
Here is my current code:
Client.cpp
#include "client.h"
#include <pugixml.hpp>
#include <map>
#include <sstream>
#include <string>
#include "task.h" // Generate the API message, not relevant
Client::Client(const QString& server, const QString& port, QObject* parent):
QObject(parent)
{
connectToServer(server, port);
connect(&socket_, &QTcpSocket::readyRead, this, &Client::getResult);
}
void Client::connectToServer(const QString& server, const QString& port)
{
bool ok;
int portNumber = port.toInt(&ok);
if (ok) {
if (socket_.state() == QTcpSocket::SocketState::ConnectedState)
socket_.disconnectFromHost();
socket_.connectToHost(server, portNumber);
} else {
throw tr("Cannot connect to server %1 on port %2. Make sure the provided information are correct.")
.arg(server)
.arg(port);
}
}
void Client::throwOnError(const pugi::xml_document& doc)
{
pugi::xpath_node_set errors = doc.select_nodes("/EXECUTION/TASK/RESULTSET/RESULT/MESSAGE");
std::string error_message = "";
for (pugi::xpath_node_set::const_iterator it = errors.begin(); it != errors.end(); ++it)
{
pugi::xml_node node = it->node();
if (std::string(node.attribute("type").value()) == "Error" ||
std::string(node.attribute("type").value()) == "Warning")
error_message += node.child_value();
}
if (!error_message.empty())
throw std::exception(error_message.c_str());
}
void Client::sendMessage(const QString &message)
{
outMessage = message;
result_.clear();
socket_.write(message.toUtf8());
}
void Client::getResult()
{
emit startReading();
while (socket_.bytesAvailable() > 0) {
result_.append(socket_.readAll());
socket_.flush();
}
resultMessage = QString(result_);
emit finishedReading();
}
void Client::login(const QString& user, const QString& password, const QString& project)
{
std::map<QString, QString> whereFields {{"userName", user}, {"password", password}};
QString request = prepareMessage("Login", "Security", std::map<QString, QString>(), whereFields); // Generates the XML message for the API
sendMessage(request);
// Wait for data to arrive - How ?
std::stringstream xmlResult = getXmlData(result_); // Remove the header from the API response and convert the QByteArray to a std::stringstream
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load(xmlResult);
throwOnError(doc);
pugi::xpath_node session = doc.select_node("/EXECUTION/TASK/RESULTSET/DATASETS/DATASET/secId");
sessionId_ = QString::fromStdString(session.node().first_child().value());
projectName_ = project;
emit taskCompleted();
}
Client.h
#ifndef Client_H
#define Client_H
#include <QObject>
#include <QTcpSocket>
#include <QByteArray>
#include <map>
#include <set>
#include "pugixml.hpp"
class Client : public QObject
{
Q_OBJECT
public:
Client(QObject* parent = 0) : QObject(parent) {}
Client(const QString& server, const QString& port, QObject* parent = 0);
// Connection
void connectToServer(const QString& server, const QString& port);
void login(const QString& user, const QString& password, const QString& project);
void logout();
QString const getSessionId() { return sessionId_; }
void throwOnError(const pugi::xml_document& doc);
QString sessionId() const { return sessionId_; }
QString outMessage; // For testing
QString resultMessage; // For testing
signals:
void ready();
void startReading();
void finishedReading();
void taskCompleted();
private slots:
void getResult();
private:
void sendMessage(const QString& message);
QTcpSocket socket_;
QString sessionId_;
QString projectName_;
QByteArray result_;
};
#endif // Client_H

Sockets with QT

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.
}
}

QObject: no such slot QThread::readyRead()

I am trying to figure out how to correctly use Qt TCP Sockets, as well as multithreading. I want, as a test project in support of something more complex but similar I will try in the future, to do the following: a simple application that either listens for exactly one incoming connection, or connects to a serversocket; next it prints everything it receives over that socket.
The situation where I connect to a serversocket (I use netcat with the -l option for this) works fine: everything netcat sends to my application is printed correctly. However, when I use my program to listen for that one incoming connection (generated by netcat), the connecting succeeds but then I get this runtime error:
QObject::connect: No such signal QThread::readyRead() in ..\QTcpTest\listener.cpp:8
Here is the entire code (don't mind the plain C I/O I use sometimes, I'll remove this later):
[ main.cpp ]
#include "peer.h"
#include <QCoreApplication>
#include <QThread>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static bool askIfServer();
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Peer *p;
int rval;
if (askIfServer())
p = new Peer;
else
p = new Peer(false);
rval = a.exec();
delete p;
return rval;
}
static bool askIfServer()
{
bool isServer;
char ibuf[BUFSIZ];
fputs("Choose \'host\' or \'join\': ", stderr);
fgets(ibuf, BUFSIZ, stdin);
ibuf[strlen(ibuf) - 1] = '\0';
fflush(stdin);
if (strcmp(ibuf, "host") == 0)
isServer = true;
else if (strcmp(ibuf, "join") == 0)
isServer = false;
else
{
fputs("Failure.\n", stderr);
exit(-1);
}
return isServer;
}
[ peer.h ]
#ifndef PEER_H
#define PEER_H
#include "listener.h"
#include <QObject>
#include <QThread>
#include <QtNetwork/QTcpSocket>
#include <QtNetwork/QTcpServer>
class Peer : public QObject
{
Q_OBJECT
public:
static const quint16 PORT = 5483;
explicit Peer(bool isHost = true, QString hostname = "localhost", QObject *parent = 0);
public slots:
void acceptPeer();
private:
bool _isHost;
QTcpServer *_server;
QTcpSocket *_socket;
QThread *_lThread;
Listener *_listener;
};
#endif // PEER_H
[ peer.cpp ]
#include "peer.h"
Peer::Peer(bool isHost, QString hostname, QObject *parent) :
QObject(parent),
_isHost(isHost)
{
if (_isHost)
{
_server = new QTcpServer;
connect(_server, SIGNAL(newConnection()), this, SLOT(acceptPeer()));
_server->listen(QHostAddress::Any, PORT);
}
else
{
_socket = new QTcpSocket;
connect(_socket, SIGNAL(hostFound()), this, SLOT(acceptPeer()));
_socket->connectToHost(hostname, PORT);
}
}
void Peer::acceptPeer()
{
disconnect(this, SLOT(acceptPeer()));
if (_isHost)
{
_socket = _server->nextPendingConnection();
delete _server;
_server = NULL;
}
_lThread = new QThread;
_listener = new Listener(_socket);
_listener->moveToThread(_lThread);
_lThread->start();
}
[ listener.h ]
#ifndef LISTENER_H
#define LISTENER_H
#include <iostream>
#include <QObject>
#include <QByteArray>
#include <QtNetwork/QTcpSocket>
using std::cout;
class Listener : public QObject
{
Q_OBJECT
public:
explicit Listener(QTcpSocket *socket, QObject *parent = 0);
public slots:
void acceptData();
private:
QTcpSocket *_socket;
};
#endif // LISTENER_H
[ listener.cpp ]
#include "listener.h"
Listener::Listener(QTcpSocket *socket, QObject *parent) :
QObject(parent),
_socket(socket)
{
// I guess this is where it goes wrong
connect(_socket, SIGNAL(readyRead()), this, SLOT(acceptData()), Qt::QueuedConnection);
}
void Listener::acceptData()
{
QByteArray data = _socket->readAll();
cout << data.constData();
}
The thing I do not get is that the error message claims that I try to connect some signal from QThread (and I clearly do not: see listener.cpp:8); even stranger is that this only happens when the socket is created by the QTcpServer instance, not in the other case. What am I missing?
EDIT: SOLVED
See my own answer.
I do not use an extra thread anymore (see comment). The problem was deleting the QTcpServer instance in Peer::acceptPeer(), once a connection was established. I thought that I could delete it because I only need that one socket QTcpServer::nextPendingConnection() returns. Apparently this is wrong, the socket is probably destroyed as well, leaving me with a rogue pointer (I think) crashing the program. Now I only call _server->pauseAccepting(); right after I get the socket, and all works fine.
Here is the change I've made:
void Peer::acceptPeer()
{
disconnect(this, SLOT(acceptPeer()));
if (_isHost)
{
_socket = _server->nextPendingConnection();
_server->pauseAccepting(); // no deletion
}
_listener = new Listener(_socket);
}