I am writing a multithread server but during the compile in "mythraed" class i get the following errors":
1) Cannot connect (null)::readyRead() to mythread::readyRead()
2) Cannot connect (null)::disconnected() to mythread::disconnected()
How should i fix it?
here is my code:
void mythread::run()
{
qDebug() << " Thread started";
connect(m_client, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
connect(m_client, SIGNAL(disconnected()), this, SLOT(disconnected()));
qDebug() << " Client connected";
exec();
}
void mythread::readyRead()
{
QByteArray Data = m_client->readAll();
qDebug()<< " Data in: " << Data;
m_client->write(Data);
}
void mythread::disconnected()
{
qDebug() << " Disconnected";
m_client->deleteLater();
exit(0);
}
myclient:
myclient::myclient(QObject* parent): QObject(parent)
{
QObject::connect(&m_client, SIGNAL(connected()),this, SLOT(startTransfer()));
}
void myclient::start(QString address, quint16 port)
{
QHostAddress LocalHost;
m_client.connectToHost(LocalHost, 6666);
}
void myclient::startTransfer()
{
m_client.write("Hello", 5);
}
Apparently, m_client is nullptr.
if (m_client) {
connect(m_client, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
}
Also you don't need explicitly disconnect your connection, from documentation:
All signals to and from the object are automatically disconnected, and any pending posted events for the object are removed from the event queue. However, it is often safer to use deleteLater() rather than deleting a QObject subclass directly.
Related
I am writing simple client server program in Qt that server is multi thread.
For one server it work correctly and it can send message from client to server but in multi thread form it doesn't work, it connect to thread and also show the message "client connected" but it can't show message sent from client!
I searched a lot bud I couldn't find what is the problem and any solution for it.. Here is my code:
Could you please help me. Thanks in advance.
myserver.cpp
#include "myserver.h"
#include "mythread.h"
myserver::myserver(QObject * parent): QTcpServer(parent)
{
}
void myserver::startserver()
{
int port = 6666;
if (!this - > listen(QHostAddress::Any, port)) {
qDebug() << "Could not start server ";
} else {
qDebug() << "Listening to port ";
}
}
void myserver::incomingConnection(qintptr socketDescriptor)
{
qDebug() << socketDescriptor << " Connecting...";
mythread * thread = new mythread(socketDescriptor, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread - > start();
}
mythread.cpp
#include "mythread.h"
#include "myserver.h"
mythread::mythread(qintptr ID, QObject *parent) : QThread(parent)
{
this->socketDescriptor = ID;
}
void mythread::run()
{
qDebug() << " Thread started";
socket = new QTcpSocket();
if(!socket->setSocketDescriptor(this->socketDescriptor)) {
emit error(socket->error());
return;
}
connect(socket, SIGNAL(readyRead()), this, SLOT(readSocket()));
qDebug() << socketDescriptor << " Client connected";
}
void mythread::readSocket()
{
QByteArray Data = socket->readAll();
qDebug()<< socketDescriptor <<" Data in: " << Data;
socket->write(Data);
}
If you read the documentation for the QThread::run function you will see
Returning from this method will end the execution of the thread.
You need to call the QThread::exec function to enter the thread event loop.
I am writing multi thread server but i have problem in accept connection and start read function. i don't know where i should write them..
here is my code:
"mythread.cpp"
#include "mythread.h"
#include "myserver.h"
mythread::mythread(qintptr ID, QObject *parent) :
QThread(parent)
{
this->socketDescriptor = ID;
}
void mythread::run()
{
qDebug() << " Thread started";
}
void mythread::acceptConnection()
{
c_client = s_server.nextPendingConnection();
connect(c_client,SIGNAL(readyRead()),
this, SLOT(startRead()));
}
void mythread::startRead()
{
char buffer[1024] = {0};
c_client->read(buffer, c_client->bytesAvailable());
qDebug() << buffer;
}
void mythread::readyRead()
{
QByteArray Data = socket->readAll();
qDebug() << socketDescriptor << " Data in: " << Data;
socket->write(Data);
}
void mythread::disconnected()
{
qDebug() << socketDescriptor << " Disconnected";
socket->deleteLater();
exit(0);
}
"myserver.cpp"
#include "myserver.h"
#include "mythread.h"
myserver::myserver(QObject *parent) :
QObject(parent)
{
}
void myserver::startserver()
{
int port = 1234;
if(s_server.listen(QHostAddress::Any, port))
{
qDebug() << "Could not start server";
}
else
{
qDebug() << "Listening to port " << port ;
}
}
void myserver::incomingconnection(int socketDescriptor)
{
connect(&s_server, SIGNAL(newConnection()),
this, SLOT(acceptConnection()));
s_server.listen(QHostAddress::Any, 1234);
qDebug() << socketDescriptor << " Connecting...";
mythread *thread = new mythread(socketDescriptor,this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
i would be grateful if you help me.
You are not using QThread very well. you can use SIGNAL and SLOTS ,and MoveToThread() function. google it.
when you use QThread, the code in Run() function will be run in another thread. acceptConnection will run in main thread.
also search for nextPendingConnection();
void myserver::incomingconnection(int socketDescriptor)
{
connect(&s_server, SIGNAL(newConnection()),this, SLOT(acceptConnection()));
...
is not OK. this connect should be called once (maybe constructor). not for any incomming connection.
I have a server that can handle multiple threads. The server starts and listens, but it is having trouble echoing when an incoming connection is pending.
I am using telnet to open the socket and send data to the server. However, the server only displays that it's listening, but doesn't echo any of the data I type through telnet or signify that there is an incoming connection. I shut off Windows firewall for private networks and still...nothing.
Also tried seeing if the server error string had anything useful to say, but all it is just an empty string.
This is a complete mystery to me and if anyone had anything constructive to note, it'd be much appreciated. Code for the thread and server is below.
server.cpp
#include "myserver.h"
MyServer::MyServer(QObject *parent) :
QTcpServer(parent)
{
}
void MyServer::StartServer()
{
if(!this->listen(QHostAddress::Any,1234))
{
qDebug() << "Could not start server";
}
else
{
qDebug() << "Listening...";
}
}
void MyServer::incomingConnection(int socketDescriptor)
{
qDebug() << socketDescriptor << " Connecting...";
MyThread *thread = new MyThread(socketDescriptor,this);
connect(thread, SIGNAL(finished()),thread, SLOT(deleteLater()));
thread->start();
}
thread.cpp
#include "mythread.h"
MyThread::MyThread(int ID, QObject *parent) :
QThread(parent)
{ this->socketDescriptor = ID;
}
void MyThread::run()
{
qDebug() << socket->errorString();
//thread starts here
qDebug() << socketDescriptor << " Starting thread";
socket = new QTcpSocket();
if(!socket->setSocketDescriptor(this->socketDescriptor))
{
emit error(socket->error());
return;
}
connect(socket,SIGNAL(readyRead()),this,SLOT(readyRead()),Qt::DirectConnection);
connect(socket,SIGNAL(disconnected()),this,SLOT(disconnected()),Qt::DirectConnection);
qDebug() << socketDescriptor << " Client Connected";
exec();
}
void MyThread::readyRead()
{
QByteArray Data = socket->readAll();
qDebug() << socketDescriptor << " Data in: " << Data;
socket->write(Data);
}
void MyThread::disconnected()
{
qDebug() << socketDescriptor << " Disconnected";
socket->deleteLater();
exit(0);
}
Which version of Qt are you using? In Qt 5, the parameter for the function incomingConnection is of type qintptr and not int. Have a look at the following links:
incomingConnection - Qt 5
Qt 5 - Multithreaded server tutorial
QTcpServer is supposed to emit the newConnection() signal whenever it receives a new client connection. I am able to connect to the server I created, even telnet to it. But in the server implementation, I have connected the newConnection() signal to a slot and it never gets invoked.
Can you please look at my code and tell me what is it that I am doing wrong ?
First the header :
#include <data_model.pb.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <QtNetwork>
#include <QVector>
#include <iostream>
#include <QAbstractSocket>
#include <QDebug>
class QTcpServer;
class QNetworkSession;
class superServer : public QObject
{
Q_OBJECT
public:
explicit superServer(QObject *parent = 0);
data_model::terminal_data fetch_next_record();
void route_data();
private slots:
void sessionOpened();
public slots:
void newTerminalConnection();
void errorconnecting(QAbstractSocket::SocketError socketError);
private:
QTcpServer *tcpServer;
QNetworkSession *networkSession;
QVector<QTcpSocket*> liveConnections;
};
#endif // SUPERSERVER_HPP
Now the implementation:
#include <superServer.hpp>
void superServer::newTerminalConnection()
{
qDebug() << "someone connected ...";
std::cout << "someone connected ..." << std::endl;
QTcpSocket *socket = tcpServer->nextPendingConnection();
liveConnections.push_back(socket);
}
superServer::superServer(QObject *parent) :
QObject(parent)
{
tcpServer = new QTcpServer();
if(!tcpServer->listen(QHostAddress::Any, 9889))
qDebug() << "Server could not start";
else
qDebug() << "Server started!";
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newTerminalConnection()));
connect(tcpServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(errorconnecting(QAbstractSocket::SocketError)));
}
void superServer::errorconnecting(QAbstractSocket::SocketError socketError)
{
qDebug() << "error connecting to client";
}
Also, I am connecting like this:
void tradeView::doConnect()
{
socket = new QTcpSocket(this);
connect(socket, SIGNAL(connected()),this, SLOT(connected()));
connect(socket, SIGNAL(disconnected()),this, SLOT(disconnected()));
connect(socket, SIGNAL(bytesWritten(qint64)),this, SLOT(bytesWritten(qint64)));
connect(socket, SIGNAL(readyRead()),this, SLOT(readyRead()));
qDebug() << "connecting...";
// this is not a blocking call
socket->connectToHost("localhost", 9889);
// we need to wait...
if(!socket->waitForConnected(5000))
{
qDebug() << "Error: " << socket->errorString();
}
}
void tradeView::connected()
{
qDebug() << "connected...";
}
void tradeView::disconnected()
{
qDebug() << "disconnected...";
}
void tradeView::bytesWritten(qint64 bytes)
{
qDebug() << bytes << " bytes written...";
}
The client connects !!! Even Telnet works !!!
But that signal does not get emitted. Can you please tell me what is wrong ?
Trust me I have looked at more than a dozen related threads here on SO and qt-center etc. None give a solution.
Please help.
Programm works, but client can't connect to the server. (i run 2 examples of programm: client and server). I can't find where is my mistake.
I wrote the codes below.You will see what i want to do if you look at main function.
//main.cpp
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//выбор клиента или сервера
cout << "1.Client\n2.Server\n";
switch (_getch())
{
case 49:
{
cout<<"client init\n";
Client* cli = new Client("localhost",1922);
string line;
while(line!="exit") {
cout << "Message : ";
cin >> line;
cli->SendData(QString(line.c_str()));
}
break;
}
case 50:
{
cout<<"server init\n";
Server* srv = new Server(0, 1922);
break;
}
}
return a.exec();
}
//server.h
class Server : public QTcpServer {
Q_OBJECT public : Server(QObject *parent = 0, quint16 port = 1922);
virtual ~Server();
private
slots:
void acceptConnection();
void startRead();
void disconnected();
private:
QTcpServer *tcpServer;
QTcpSocket *client;
};
//server.cpp
Server::Server(QObject *parent, quint16 port) : QTcpServer(parent) {
//tcpServer = new QTcpServer(this);
connect(this, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
if (!this->listen(QHostAddress::Any, port))
std::cout << "unable to start server\n"
<< this->errorString().toUtf8().constData() << endl;
else
std::cout << "server started\n";
}
Server::~Server() {
//delete client;
close();
}
void Server::acceptConnection() {
std::cout << "new connection!\n";
client = nextPendingConnection();
connect(client, SIGNAL(readyRead()), this, SLOT(startRead()));
connect(client, SIGNAL(disconnected()), this, SLOT(disconnected()));
qDebug() << "New client from:" << client->peerAddress().toString();
}
void Server::startRead() {
client = (QTcpSocket *)sender();
while (client->canReadLine()) {
QString line = QString::fromUtf8(client->readLine()).trimmed();
qDebug() << "Client :" << line;
client->write(QString("Server : I've taken your message (:\n").toUtf8());
}
}
void Server::disconnected() {
qDebug() << "Client disconnected:" << client->peerAddress().toString();
client->write(QString("Server : I wish you didn't leave ):\n").toUtf8());
}
//} <-- EDIT: THIS IS PROBABLY AN EXTRA
//***************************************************************
//client.h
class Client : public QObject {
Q_OBJECT public : Client(const QString &add, int port, QObject *obj = 0);
void SendData(QString data);
virtual ~Client();
int status();
QString err;
private
slots:
void ReadData();
void slotConnected();
void slotError(QAbstractSocket::SocketError);
private:
QTcpSocket *socket;
};
//client.cpp
Client::Client(const QString &add, int port, QObject *obj) : QObject(obj) {
//create socket
socket = new QTcpSocket(this);
//connect
socket ->connectToHost(add, port);
connect(socket, SIGNAL(readyRead()), SLOT(ReadData()));
connect(socket, SIGNAL(connected()), SLOT(slotConnected()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this,
SLOT(slotError(QAbstractSocket::SocketError)));
}
Client::~Client() {
socket->close();
delete socket;
}
void Client::SendData(QString data) {
if (!data.isEmpty()) {
QByteArray arrBlock;
QDataStream out(&arrBlock, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_1);
out << quint16(0) << QTime::currentTime() << data;
out.device()->seek(0);
out << quint16(arrBlock.size() - sizeof(quint16));
socket->write(arrBlock);
socket->flush();
}
}
void Client::ReadData() {
QDataStream in(socket);
in.setVersion(QDataStream::Qt_5_1);
while (socket->canReadLine()) {
QString line = QString::fromUtf8(socket->readLine()).trimmed();
qDebug() << line;
}
}
void Client::slotConnected() {
socket->write(QString("Client : Server connection has been made (: \n")
.toUtf8());
}
void Client::slotError(QAbstractSocket::SocketError err) {
QString strError =
"Error: " + (err == QAbstractSocket::HostNotFoundError
? "The host was not found."
: err == QAbstractSocket::RemoteHostClosedError
? "The remote host is closed."
: err == QAbstractSocket::ConnectionRefusedError
? "The connection was refused."
: QString(socket->errorString()));
std::cout << strError.toUtf8().constData() << endl;
}
int Client::status() { return socket->state(); }
help me pls!
It's probably becouse of the while loop in main.cpp, it blocks client's event loop, and will return to event loop right after 'exit' will be typed. I mean this lines:
while (line != "exit") {
cout << "Message : ";
cin >> line;
cli.SendData(QString(line.c_str()));
}
How this can be avoided: main.cpp MUST reach return a.exec(); line to start event loop (i am excluding some ugly processEvent solutions right away ).
To send commands to cmd and NOT block event loop i used class i saw somewhere here on stackoverflow:
example of main.cpp:
QCoreApplication a(argc, argv);
qDebug()<<"Press 'q' to quit";
QTcpServer server;
qDebug()<<"Server is started -"<<server.isListening();
// Console reader to filter console input
ConsoleReader reader;
QObject::connect(&reader,SIGNAL(shutdown()),&a,SLOT(quit()));
return a.exec();
aaand behold, ConsoleReader class, header:
#ifndef CONSOLEREADER_H
#define CONSOLEREADER_H
#pragma once
#include <QObject>
#include <QSocketNotifier>
class ConsoleReader : public QObject
{
Q_OBJECT
public:
explicit ConsoleReader(QObject *parent = 0);
~ConsoleReader();
signals:
void shutdown();
public slots:
void text();
private:
QSocketNotifier* notifier;
};
#endif // CONSOLEREADER_H
source:
#include "consolereader.h"
#include <QTextStream>
#include <QDebug>
#include <unistd.h> //Provides STDIN_FILENO
ConsoleReader::ConsoleReader(QObject *parent) :
QObject(parent)
{
notifier = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read);
connect(notifier, SIGNAL(activated(int)), this, SLOT(text()));
}
void ConsoleReader::text()
{
QTextStream qin(stdin);
QString line = qin.readLine();
if (line==QString("q")){
qDebug()<<"Shutting down the server..";
emit shutdown();
}
else qDebug()<<"Unknown command: "<<line;
}
ConsoleReader::~ConsoleReader(){
delete notifier;
}
In your main function, you create both the client and the server on the stack, which will then be deleted when they go out of scope of the switch statement.
You need to dynamically allocate the objects on the heap: -
Server* pServer = new Server(0, 1922);
Client* pClient = new Client("localhost" 1922);
Although the client will remain, due to the while loop after its creation, the server will be created, start listening, then be deleted, along with the QTcpSocket, as it is has the server as its parent.
As I mentioned in my comment there is no need to create a separate QTCpServer as the server isa QTcpServer. So where you have:
Server::Server(QObject *parent, quint16 port) : QTcpServer(parent) {
tcpServer = new QTcpServer(this);
connect(this, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
if (!tcpServer->listen(QHostAddress::Any, port))
std::cout << "unable to start server\n"
<< tcpServer->errorString().toUtf8().constData() << endl;
else
std::cout << "server started\n";
}
Change to:
Server::Server(QObject *parent, quint16 port) : QTcpServer(parent) {
connect(this, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
if (!this->listen(QHostAddress::Any, port))
std::cout << "unable to start server\n"
<< this->errorString().toUtf8().constData() << endl;
else
std::cout << "server started\n";
}
I think the problem could be that its trying to do stuff with a different object rather than the 'this' object.