Non-QT server and QT client - connection using thrift - c++

REQUIREMENT
A Client Server Application
Communication will be done by thrift
Server will be running in background or invoked through terminal with no GUI
Client will be Qt based
Current Scenario and problem
Currently, the server uses TNonBlockingServer with certain number of threads(using threadmanager)
Clients connect to the server and does the job.
But, there is a certain requirement where if my server is not running and client tries to connect to it then a message box should be displayed in client's screen.
Currently program just gives a segmentation fault, so i tried using try catch, which didn't work. Upon searching i noticed that Qt doesn't support Exceptions.
Upon some more searching i came across This, but this seems to be using QT(and I still don't know if my problem can be resolved by this)
Server Code :
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
shared_ptr<workerHandlerHandler> handler(new workerHandlerHandler());
shared_ptr<TProcessor> processor(new workerHandlerProcessor(handler));
shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(15);
shared_ptr<PosixThreadFactory> threadFactory = shared_ptr<PosixThreadFactory>(new PosixThreadFactory());
threadManager->threadFactory(threadFactory);
threadManager->start();
TNonblockingServer server(processor, protocolFactory, port,threadManager);
server.serve();
Client connects using
boost::shared_ptr<TSocket> socket(new TSocket(serverip.toUtf8().data(), 59999));
boost::shared_ptr<TTransport> transport(new TFramedTransport(socket));
boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
workerHandlerClient client(protocol);
transport->open();
int pingValue = client.ping();
transport->close();

Why not use something like:
QTcpSocket *socket = new QTcpSocket();
socket->connectToHost(serverip, serverport);
if(!socket->waitForConnected(time-in-msecs))
QMessageBox::critical(some-ui-window-as-parent, "Error Title", "Error connecting Text");

If the client is Qt based, you can use QTcpSocket to connect the server :
QTcpSocket clientSocket;
By connecting the error signal of the client socket to a slot, you can display appropriate message box when an error occurs. If the server is not running and the client tries to connect, the slot is called and a message box containing the error is shown :
connect( &clientSocket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(tcpError(QAbstractSocket::SocketError)) );
clientSocket.connectToHost(ipAddress, portNo );
The slot is as :
void MyClass::tcpError(QAbstractSocket::SocketError error)
{
QMessageBox::warning( this, tr("Error"),tr("TCP error: %1").arg( clientSocket.errorString() ) );
clientSocket.disconnectFromHost();
}

I don't know what you really mean.Qt just support try and catch.
Now, I'm developing a program which is similar with your program.
I also use No-QT server and QT client, but in my code I use the struct like below:
try
{
}
catch(TException e)
{
QMessageBox::information(this, "Warn", "Thrift server has shut down");
}
And it works well

Related

How to connect with server using Secure WebSocket in Qt c++

I am creating Qt application that should be able to connect with
server using secure connection (i.e. wss://xxx.xxx.xxx.xxx:8080),
Application is working fine with none-secure connection (i.e.
ws://xxx.xxx.xxx.xxx:8443).
Protocol i am using is WebSocket. I have used library for connection.
Qt Creator 3.4.2 (opensource) Based on Qt 5.5.0 (MSVC 2013, 32 bit)
QsslSocket::supportsSsl() was returning false, then find out that i was missing openssl library files ( libeay32.dll , ssleay32.dll ) then i put these file in the path of my application and run code again now QSslSocket::supportsSsl() is returning true. but when i try to connect websocket it is showing flollowing errors.
connect(&wsocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(onError(QAbstractSocket::SocketError)), Qt::DirectConnection);
connect(&wsocket, SIGNAL(sslErrors(QList)), SLOT(onSslErrors(QList)), Qt::DirectConnection);
onSslErrors : unknown error onError : "The host name did not match any
of the valid hosts for this certificate" Error:
QAbstractSocket::SocketError(13)
code snippet from client side(Qt)
void onConnectToServer()
{
qRegisterMetaType<QAbstractSocket::SocketError>();
qRegisterMetaType<QAbstractSocket::SocketState>();
connect(&wsocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(onError(QAbstractSocket::SocketError)), Qt::DirectConnection);
connect(&wsocket, SIGNAL(sslErrors(QList<QSslError>)), SLOT(onSslErrors(QList<QSslError>)), Qt::DirectConnection);
connect(&wsocket, SIGNAL(connected()), SLOT(onConnected()), Qt::DirectConnection);
connect(&wsocket, SIGNAL(binaryMessageReceived(QByteArray)), SLOT(onBinaryMessage(QByteArray)), Qt::DirectConnection);
connect(&wsocket, SIGNAL(textMessageReceived(QString)), SLOT(onTextMessage(QString)), Qt::DirectConnection);
connect(&wsocket, SIGNAL(disconnected()), SLOT(onDisconnected()), Qt::DirectConnection);
connect(&wsocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(onStateChanged(QAbstractSocket::SocketState)), Qt::DirectConnection);
QUrl serverURL;
QWebSocket wsocket;
// some code for here and setting **serverURL**
wsocket.setPauseMode(QAbstractSocket::PauseNever);
wsocket.open(serverURL);
}
void onSslErrors(const QList<QSslError> &errors)
{
qDebug() << wsocket.errorString();
}
void onError(const QAbstractSocket::SocketError &socketError)
{
qDebug() << wsocket.errorString() << " Error:" << socketError;
}
void onConnected()
{
qDebug() << "Successfully Connected with " << serverURL;
}
void onDisconnected()
{
qDebug() << wsocket.errorString() << " CloseCode is >>> " << wsocket.closeCode();
}
void onStateChanged(QAbstractSocket::SocketState socketState)
{
qDebug() << "StateChanged : " << socketState;
}
how to resolve this any one have idea how to connect secure web socket. i did check SSL Echo Client Example but it seems like server side also should be Qt WebSocket.
Q1) How to make secure connection using Qt from client side?
NOTE: server side is configured for secure connection already.
Q2) Server side is not Qt Code and client side is Qt. does it in
secure web socket connection? (i.e. server Socket and client Socket are independent of programming Language for connection or not?)
NOTE: i'm able to connect with same server using none secure
connection.
I did found solution after all,
Before I open connection to the remote server using this line,
wsocket.open(serverURL);
I added QSslConfiguration and ignore ssl Error for self signed certificate for development , of course i will correc that in Production.
QSslConfiguration sslConfiguration = wsocket.sslConfiguration();
sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyPeer);
wsocket.setSslConfiguration(sslConfiguration);
wsocket.ignoreSslErrors();

Qt: Why is `QAbstractSocket::error(QAbstractSocket::SocketError)` signal not generated when internet is disconnected?

I am trying to achieve a signal when the internet is disconnected for an already connected SSL socket. Here is the way I have derived the QSslSocket:
struct CloudSSL::Socket : public QSslSocket
{
Q_OBJECT public:
void ConnectSlots ()
{
connect(this, SIGNAL(readyRead()), this, SLOT(ReceiveData()));
connect(this, SIGNAL(disconnected()), this, SLOT(Disconnected()));
// *** None of the above or below is invoking when internet disconnects ***
connect(this, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(Error(QAbstractSocket::SocketError)));
}
virtual ~Socket ()
{
QObject::disconnect();
QSslSocket::abort();
}
public slots:
void ReceiveData ()
{
LOG("Socket received data...");
}
void Disconnected ()
{
LOG("Socket got disconnected...");
}
void Error (QAbstractSocket::SocketError error)
{
LOG("Socket error ", error);
}
}
Here is how it's initialized:
m_pSSLSocket = new Socket;
m_pSSLSocket->setProtocol(QSsl::TlsV1_2);
m_pSSLSocket->setLocalCertificateChain(QSslCertificate::fromPath(":/Certificate.pem", QSsl::Pem));
m_pSSLSocket->setPrivateKey(QSslKey(privateKeyFile.readAll(), QSsl::Rsa));
m_pSSLSocket->setSocketOption(QAbstractSocket::LowDelayOption, true); // <---
m_pSSLSocket->setSocketOption(QAbstractSocket::KeepAliveOption, true); // <---
m_pSSLSocket->connectToHostEncrypted(SAARATHY_URL, SAARATHY_PORT);
m_pSSLSocket->ignoreSslErrors();
Things work fine in general. However, if I disable wifi in my Ubuntu PC, then I don't get any network error as expected from the QAbstractSocket::SocketError:
QAbstractSocket::NetworkError -- 7 -- An error occurred with the network
(e.g., the network cable was accidentally plugged out).
Referred following posts before this Qn:
QTcpSocket state always connected, even unplugging ethernet wire
Qt TCP/IP socket connection check
Question: What is the Qt exclusive way of receiving a signal when the internet is disconnected?
Unless the protocols you use have some sort of keep-alive, if you don't send anything nothing will be sent and no attempt of error checking will be done.
If you want to see if there's problem with a connection you actually have to send something. If a cable is unplugged or there is any other problem between you and the remote host, then (after a suitable timeout and retries) you will get an error.
To see if the remote host has closed the connection in a nice way, you have to attempt to read something, in which case the receive call will return that it has read zero bytes.

How to tell the client has end the connection during IPC using QLocalSocket?

I have two programs doing IPC using QLocalSocket & QLocalServer, I have managed to implement the connection and send the data successfully.
However, for the QLocalServer side, how can I know a connection is ended by client (like the client program quit.)?
So that I could release the resource of corresponding socket on server side?
You can connect the void QLocalSocket::disconnected() signal from QLocalHost to a slot in your class:
connect(mySocket, &QLocalSocket::disconnected, this, &MyClass::socketDisconnected, Qt::QueuedConnection);
Or you can connect to the stateChange (for more detailed version), something like:
// Connect like this
connect(mySocket, &QLocalSocket::stateChanged, this, &MyClass::socketNewState, Qt::QueuedConnection);
// Implement a slot that handles the various states...
MyClass::socketNewState(QLocalSocket::LocalSocketState socketState)
{
qDebug() << "New state is " << socketState << endl;
}

Qt TCP sockets working on Linux but not on Windows?

I am using QTcpSocket to send data between a client and a server.
The server works perfectly fine on Linux, yet on Windows it will only receive one message and not more after that. readyRead() is just never emitted again.
Does anyone know what could be the problem?
Some of the code which I deemed to be important for this question:
server sending:
void Server::sendData(Client *client, QString data)
{
if (client->socketDescriptor == socketDescriptor) {
data = data + CRLF;
// Have also tried to use socket->flush(), same problem.
socket->write(data.toUtf8());
socket->waitForBytesWritten();
}
}
server receiving:
// this slot is connected to the readyRead() signal
void Server::readData()
{
// on Windows this is called exactly once for each client
// every additional messages just don't seem to arrive at the server
QString msg = QString(socket->readAll());
emit receivedData(this, &msg);
}
I just don't get why it works on Linux, yet not on windows...

Approach to the multi client server with Qt

I'm creating a multi client server (IRC) in C++ using Qt lib. I'd like to know whether it's a good approach to the server architecture.
I'd like to avoid creating thread per connection, so I thought that I could have all client sockets in some kind of container and perform actions (like processing incoming packet) using ThreadPool.
My only concern is whether having sockets connected to the SLOT guarantees parallel client handling.
Code :
CServer::CServer(QObject *parent) : QTcpServer(parent)
{
server = new QTcpServer(this);
connect(server, SIGNAL(newConnection()), this, SLOT(newConnection()));
if(!server->listen(QHostAddress::Any, 6667))
qDebug() << "Oh noes";
}
void CServer::newConnection(){
add server->nextPendingConnection() to the container
}