QTcpSocket и несколько клиентов (проблема с сигналом)

Я разрабатываю сервер, который отвечает на несколько подключений от клиента. Но у меня есть проблема, решения которой я не нашел. Я создал класс (TcpSocket) для QTcpSocket, который разделяет сигналы и слоты для каждого соединения.

Но у меня сервер не распознает сигнал этого класса, ищет по QTcpSocket, а не по TcpSocket.

Я выложу код, может быть, вы понимаете лучше, потому что мой английский не очень хорош.

tcpsocket.h

#ifndef TCPSOCKET_H
#define TCPSOCKET_H

#include <QObject>
#include <QtNetwork>

class TcpSocket: public QTcpSocket
{
    Q_OBJECT
    QTcpSocket *Socket;
public:
    TcpSocket (QTcpSocket *);
    virtual ~TcpSocket();

public slots:
    void slotReadyRead();
    void slotConnected();
    void slotDisconnected();

signals:
    void dataReady (TcpSocket *sckt);
    void newConnection(TcpSocket *sckt);
    void lostConnection(TcpSocket *sckt);
};


#endif // TCPSOCKET_H

tcpsocket.cpp

#include "tcpsocket.h"

TcpSocket::TcpSocket(QTcpSocket * socket)
    : Socket (socket)
{
    connect(Socket, SIGNAL(readyRead()), this, SLOT (slotReadyRead()));
    connect(Socket, SIGNAL(connected()), this, SLOT(slotConnected()));
    connect(Socket, SIGNAL(disconnected()), this, SLOT(slotDisconnected()));
}

TcpSocket::~TcpSocket()
{

}

void TcpSocket::slotReadyRead()
{
    emit dataReady(this);
}

void TcpSocket::slotConnected()
{
    emit newConnection(this);
}

void TcpSocket::slotDisconnected()
{
    emit lostConnection(this);
}

сервер.h

#ifndef SERVER_H
#define SERVER_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include "custom/player.h"
#include "events.h"
#include "socketmanager.h"
#include "tcpsocket.h"

#include <QMessageBox>

namespace Ui {
class Server;
}

class Server : public QMainWindow
{
    Q_OBJECT


public:
    explicit Server(QWidget *parent = 0);
    int max_connections;
    ~Server();

private slots:
    ...
    void client_Disconnected(TcpSocket *socket);
    void client_SendedBytes(qint64 bytes);
    void client_GetBytes(TcpSocket* socket);
    ...

private:
    Ui::Server *ui;
    QTcpServer *server;
    QList<TcpSocket *> client;
    ...

};

#endif // SERVER_H

server.cpp

int j; // connection count
void Server::server_Connected()
{
    client.insert(j, (TcpSocket*)server->nextPendingConnection());
    TcpSocket *sckt = client[j];
    // error:
    connect(sckt, SIGNAL(newConnection(TcpSocket*)), this, SLOT(client_GetBytes(TcpSocket*)));
    connect(sckt, SIGNAL(lostConnection(TcpSocket*)), this, SLOT(client_Disconnected(TcpSocket*)));

    QByteArray block;
    QTextStream out(&block, QIODevice::WriteOnly);
    out << "accepted";

    ui->log->append(QString("Host connected: %1, index %2").arg(sckt->localAddress().toString()).arg(j));

    std::string stdString = "accepted";
    QByteArray byteArray(stdString.c_str(), stdString.length());
    qint64 len = sckt->write(byteArray);
    if(len != byteArray.size())
        ui->log->append("Error!");
    sckt->flush();

    j++;
}

void Server::client_Disconnected(TcpSocket *socket)
{
...
}

void Server::client_GetBytes(TcpSocket *socket)
{
...
}

Ошибка:

QObject::connect: Нет такого сигнала QTcpSocket::newConnection(TcpSocket*) в ..\SOLEditorServer\server.cpp:45 QObject::connect: (имя получателя: "Сервер")

QObject::connect: Нет такого сигнала QTcpSocket::lostConnection(TcpSocket*) в ..\SOLEditorServer\server.cpp:46 QObject::connect: (имя получателя: "Сервер")

также полный код (сервер)

#include "server.h"
#include "ui_server.h"

#include <QHostAddress>

Server::Server(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Server)
{
    max_connections = 20;
    SM = new SocketManager();
    ui->setupUi(this);
    server = new QTcpServer(this);
    connect(server, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(server_Error()));
    connect(server, SIGNAL(newConnection()), this, SLOT(server_Connected()));

    event = new Events(ui->log);
    setWindowFlags(Qt::WindowCloseButtonHint);
}

Server::~Server()
{
    delete ui;
}

void Server::on_pushButton_clicked()
{
    QHostAddress host;
    host.setAddress(ui->txt_ip->text());

    server->listen(host, ui->txt_port->value());
    ui->log->append("Connected!");
}

void Server::server_Error()
{
    ui->log->append(server->errorString());
}

int j;
void Server::server_Connected()
{
    client.insert(j, (TcpSocket*)server->nextPendingConnection());
    TcpSocket *sckt = client[j];
    connect(sckt, SIGNAL(newConnection(TcpSocket*)), this, SLOT(client_GetBytes(TcpSocket*)));
    connect(sckt, SIGNAL(lostConnection(TcpSocket*)), this, SLOT(client_Disconnected(TcpSocket*)));

    QByteArray block;
    QTextStream out(&block, QIODevice::WriteOnly);
    out << "accepted";

    ui->log->append(QString("Host connected: %1, index %2").arg(sckt->localAddress().toString()).arg(j));

    std::string stdString = "accepted";
    QByteArray byteArray(stdString.c_str(), stdString.length());
    qint64 len = sckt->write(byteArray);
    if(len != byteArray.size())
        ui->log->append("Error!");
    sckt->flush();

    j++;
}

void Server::client_Disconnected(TcpSocket *socket)
{
    ui->log->append(QString("Desconectado. (%1)").arg(socket->localAddress().toString()));
    client.removeAt(client.indexOf(socket));
}

void Server::client_SendedBytes(qint64 bytes)
{
    QString dataxD = QString::number(bytes);
    ui->log->append(QString("%1 bytes enviados.").arg(dataxD));
}

void Server::client_GetBytes(TcpSocket *socket)
{
    QByteArray buffer;
    buffer.resize(socket->bytesAvailable());
    socket->read(buffer.data(), buffer.size());
    QString data(buffer);

    if(data.startsWith("REGISTER "))
    {
        QString received = data.split("REGISTER ")[1];
        ui->log->append(received);
        QString user = received.split(":")[0];
        QString key = received.split(":")[1];
        playerList.append(user);
        playerKey.append(key);
        event->eventNewPlayer(user);
        SM->sendPacketToAll(client, QString("GREETING %1").arg(user));
    } else if(data.startsWith("CHAT("))
    {
        QString UserData = data.split("CHAT(")[1].split(")")[0];
        if(!checkUser(UserData))
        {
            ui->log->append("Username without a valid hash!");
            return;
        }
        QString User = getUsernameFromData(UserData);
        QString Message = data.split(QString("CHAT(%1) ").arg(UserData))[1];
        event->eventNewChatmessage(Message, User);
        SM->sendPacketToAll(client, QString("CHAT(%1) %2").arg(User).arg(Message));
    }
}

bool Server::checkUser(QString usernamedata)
{
    if(!usernamedata.contains(":"))
        return false;

    QString username = usernamedata.split(":")[0];
    QString key = usernamedata.split(":")[1];

    if(!playerList.contains(username) || !playerKey.contains(key))
        return false;

    int playerIndex = playerList.indexOf(username);
    QString hashFromList = playerKey[playerIndex];

    if(hashFromList != key)
        return false;

    return true;
}

bool Server::checkUser2(QString username, QString key)
{
    if(!playerList.contains(username) || !playerKey.contains(key))
        return false;

    int playerIndex = playerList.indexOf(username);
    QString hashFromList = playerKey[playerIndex];

    if(hashFromList != key)
        return false;

    return true;
}

QString Server::getUsernameFromData(QString usernamedata)
{
    if(!usernamedata.contains(":"))
        return "Unknow";

    QString username = usernamedata.split(":")[0];
    return username;
}

QString Server::getUserkeyFromData(QString usernamedata)
{
    if(!usernamedata.contains(":"))
        return "Unknow";

    QString key = usernamedata.split(":")[1];
    return key;
}

void Server::on_pushButton_2_clicked()
{
    /*std::string stdString = "BANNED";
    QByteArray byteArray(stdString.c_str(), stdString.length());
    clientConnection->write(byteArray);*/
}

полный сервер.ч

#ifndef SERVER_H
#define SERVER_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include "custom/player.h"
#include "events.h"
#include "socketmanager.h"
#include "tcpsocket.h"

#include <QMessageBox>

namespace Ui {
class Server;
}

class Server : public QMainWindow
{
    Q_OBJECT


public:
    explicit Server(QWidget *parent = 0);
    int max_connections;
    ~Server();

private slots:
    void on_pushButton_clicked();
    void server_Error();
    void server_Connected();
    void client_Disconnected(TcpSocket *socket);
    void client_SendedBytes(qint64 bytes);
    void client_GetBytes(TcpSocket* socket);
    void on_pushButton_2_clicked();
    bool checkUser(QString usernamedata);
    bool checkUser2(QString username, QString key);
    QString getUsernameFromData(QString usernamedata);
    QString getUserkeyFromData(QString usernamedata);

private:
    Ui::Server *ui;
    QTcpServer *server;
    QList<TcpSocket *> client;
    QStringList playerList;
    QStringList playerKey;
    Events *event;
    SocketManager *SM;

};

#endif // SERVER_H

person Niunzin    schedule 21.09.2014    source источник
comment
Я не вижу здесь никакой ошибки. Может быть, поделитесь полным кодом, чтобы мы могли изучить его более тщательно.   -  person Michał Walenciak    schedule 21.09.2014
comment
Готово, спасибо за ответ. = Д   -  person Niunzin    schedule 21.09.2014
comment
Привет ! Я полагаю, что clean/qmake/make снова ничего не решит? Одна странность в вашей ошибке заключается в том, что в строке 45/46 тип вашего объекта TcpSocket*, а в вашей ошибке указано QTcpSocket::signalName(..). Как будто в заголовке TcpSocket не было найдено такого сигнала или как если бы sckt (l.45/46) был неявно приведен.   -  person Martin    schedule 21.09.2014
comment
Эй, спасибо за ваш ответ! Я починил это! - (я опубликую решение)   -  person Niunzin    schedule 21.09.2014
comment
-1 так как это стена текста, и вы нигде не описываете, что вы пытаетесь сделать.   -  person Kuba hasn't forgotten Monica    schedule 22.09.2014
comment
Публикация всего кода — это не то же самое, что публикация минимального тестового примера. Предоставление минимального тестового примера показывает разумные усилия. Бросить весь проект в вопрос почти грубо.   -  person Kuba hasn't forgotten Monica    schedule 22.09.2014


Ответы (1)


Фиксированный!

Модификации:

class TcpSocket: public QTcpSocket // old
class TcpSocket: public QObject // new

// old
void dataReady (TcpSocket *sckt);
void newConnection(TcpSocket *sckt);
void lostConnection(TcpSocket *sckt);

// new
void dataReady(QTcpSocket *sckt);
void newConnection(QTcpSocket *sckt);
void lostConnection(QTcpSocket *sckt);

// old
TcpSocket::TcpSocket(QTcpSocket * socket)
    : Socket (socket)
{
    connect(Socket, SIGNAL(readyRead()), this, SLOT (slotReadyRead()));
    connect(Socket, SIGNAL(connected()), this, SLOT(slotConnected()));
    connect(Socket, SIGNAL(disconnected()), this, SLOT(slotDisconnected()));
}

// new
TcpSocket::TcpSocket (QTcpSocket * socket)
    : Socket (socket)
{
    this->sock = socket;
    connect(socket, SIGNAL(readyRead()), this, SLOT (slotReadyRead()));
    connect(socket, SIGNAL(connected()), this, SLOT(slotConnected()));
    connect(socket, SIGNAL(disconnected()), this, SLOT(slotDisconnected()));
}

// old
void TcpSocket::slotReadyRead()
{
    emit dataReady(this);
}

void TcpSocket::slotConnected()
{
    emit newConnection(this);
}

void TcpSocket::slotDisconnected()
{
    emit lostConnection(this);
}

// new
void TcpSocket::slotReadyRead()
{
    emit dataReady(this->sock);
}

void TcpSocket::slotConnected()
{
    emit newConnection(this->sock);
}

void TcpSocket::slotDisconnected()
{
    emit lostConnection(this->sock);
}

// old
public:
    TcpSocket (QTcpSocket *);
    virtual ~TcpSocket();

// new
public:
    TcpSocket (QTcpSocket *);
    QTcpSocket *sock;

Готово, теперь просто используйте функцию connect(), например:

QTcpSocket *socket = (your QTcpSocket);
TcpSocket *tcpSocket = new TcpSocket(socket);
connect(tcpSocket, SIGNAL(dataReady(QTcpSocket*)), this, SLOT(your_slot(QTcpSocket*)));

Вы мне очень помогли, извините. Удачи, если у кого-то такая же проблема, как у меня (не решена), пожалуйста, свяжитесь со мной!

person Niunzin    schedule 21.09.2014
comment
Вы должны сосредоточиться на одном аспекте решения и опубликовать код, демонстрирующий, что этот аспект исправлен. Вопрос и ответ слишком велики, чтобы быть полезными для других. - person Kuba hasn't forgotten Monica; 22.09.2014