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