Question

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!

Was it helpful?

Solution

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

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top