Программа работает, но клиент не может подключиться к серверу. (Я запускаю 2 примера программы: клиент и сервер). Я не могу найти, где моя ошибка.
Я написал коды ниже. Вы увидите, что я хочу сделать, если вы посмотрите на основную функцию.
//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(); }
помогите мне пожалуйста!
Вероятно, это из-за цикла while в main.cpp, он блокирует цикл событий клиента и вернется в цикл событий сразу после того, как будет напечатан ‘exit’. Я имею в виду эти строки:
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();
ааа, вот 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;
}
В вашей основной функции вы создаете в стеке и клиента, и сервер, которые затем удаляются, когда они выходят за рамки оператора switch.
Вам нужно динамически распределять объекты в куче: —
Server* pServer = new Server(0, 1922);
Client* pClient = new Client("localhost" 1922);
Хотя клиент останется, из-за цикла while после его создания сервер будет создан, начните прослушивание, затем удалите его вместе с QTcpSocket, так как он имеет сервер в качестве родителя.
Как я упоминал в своем комментарии, нет необходимости создавать отдельный 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.