2

程序工作,但客户端无法连接到服务器。(我运行 2 个程序示例:客户端和服务器)。我找不到我的错误在哪里。

我写了下面的代码。如果你看一下 main 函数,你会看到我想要做什么。

//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(); }

请帮帮我!

4

3 回答 3

1

在您的 main 函数中,您在堆栈上创建客户端和服务器,然后当它们超出 switch 语句的范围时将被删除。

您需要动态分配堆上的对象:-

Server* pServer = new Server(0, 1922);

Client* pClient = new Client("localhost" 1922);

尽管客户端将保留,但由于其创建后的 while 循环,服务器将被创建,开始侦听,然后与 QTcpSocket 一起被删除,因为它具有服务器作为其父级。

于 2013-11-20T11:18:39.123 回答
1

正如我在评论中提到的,不需要创建单独的 QTCpServer,因为服务器是 QTcpServer。所以你在哪里:

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

改成:

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

我认为问题可能在于它试图用不同的对象而不是“this”对象来做事。

于 2013-11-20T11:44:01.580 回答
1

这可能是由于 main.cpp 中的 while 循环,它阻塞了客户端的事件循环,并在输入“退出”后立即返回事件循环。我的意思是这行:

while (line != "exit") {
  cout << "Message : ";
  cin >> line;
  cli.SendData(QString(line.c_str()));
}

如何避免这种情况:main.cpp 必须到达return a.exec();行以启动事件循环(我立即排除了一些丑陋的processEvent解决方案)。

为了向 cmd 发送命令而不是阻止事件循环,我使用了我在 stackoverflow 上某处看到的类:

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 看,ConsoleReader类,标题:

#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

资源:

#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;
}
于 2013-11-20T12:26:53.613 回答