QTcpSocket не подключается

Я пытаюсь настроить соединение QTcpSocket. Я работаю над простым приложением, которое включает двунаправленную связь через один сокет TCP.

Я тестирую свой код, запуская два экземпляра одного и того же приложения и подключая оба к QHostAddress::Broadcast. Когда я запускаю свой код, я получаю следующую последовательность состояний:

  1. QAbstractSocket::HostLookupState -- "Сокет выполняет поиск имени хоста".
  2. QAbstractSocket::ConnectingState -- "Сокет начал устанавливать соединение".
  3. QAbstractSocket::UnconnectedState -- "Сокет не подключен".
  4. QAbstractSocket::SocketError -- "Отказано в доступе".

РЕДАКТИРОВАТЬ: После некоторой дальнейшей отладки я обнаружил, что элемент № 4 на самом деле был Ошибкой отказа в соединении.

Ниже мой код:

#include "widget.h"
#include "ui_widget.h"
#include <string>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
}

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

void Widget::on_connect_clicked()
{
    if (!m_socket)
    {
        m_socket = new QTcpSocket(this);
        m_socket->setSocketOption(QAbstractSocket::KeepAliveOption,1);
    }

    connect(m_socket, SIGNAL(readyRead()), SLOT(readSocketData()), Qt::UniqueConnection);
    connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(connectionError(QAbstractSocket::SocketError)), Qt::UniqueConnection);
    connect(m_socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(tcpSocketState(QAbstractSocket::SocketState)), Qt::UniqueConnection);
    connect(m_socket, SIGNAL(disconnected()), SLOT(onConnectionTerminated()), Qt::UniqueConnection);
    connect(m_socket, SIGNAL(connected()), SLOT(onConnectionEstablished()), Qt::UniqueConnection);

    if(!(QAbstractSocket::ConnectedState == m_socket->state()))
    {
        m_socket->connectToHost(QHostAddress::Broadcast, ui->port->value(), QIODevice::ReadWrite);
    }

}

void Widget::readSocketData()
{
    while(m_socket->bytesAvailable())
    {
        QTextStream T(m_socket);
        ui->incoming->addItem(T.readAll());
    }
}


void Widget::on_send_clicked()
{
    sendMessage(ui->message->text());
}

void Widget::sendMessage(QString msg)
{
    QByteArray dataSend;
    QDataStream dataStream(&dataSend, QIODevice::WriteOnly);
    dataStream.setByteOrder(QDataStream::LittleEndian);
    dataStream << msg.length();
    dataSend.append(msg);

    m_socket->write(dataSend, dataSend.length());
}

void Widget::connectionError(QAbstractSocket::SocketError socketError)
{
    std::string errorStr = "ERROR: " + m_socket->errorString().toStdString();
    QMessageBox::information(this, tr("Tcp Server Client"), tr(errorStr.c_str()));
}

void Widget::tcpSocketState(QAbstractSocket::SocketState socketState)
{
    switch (socketState) {
        case QAbstractSocket::UnconnectedState:
            QMessageBox::information(this, tr("Tcp Server Client"), tr("The socket is not connected."));
            break;
        case QAbstractSocket::HostLookupState:
            QMessageBox::information(this, tr("Tcp Server Client"), tr("The socket is performing a hostname lookup."));
            break;
        case QAbstractSocket::ConnectedState:
            QMessageBox::information(this, tr("Tcp Server Client"), tr("A connection is established."));
            break;
        case QAbstractSocket::ConnectingState:
            QMessageBox::information(this, tr("Tcp Server Client"), tr("The socket has started establishing a connection."));
            break;
        case QAbstractSocket::BoundState:
            QMessageBox::information(this, tr("Tcp Server Client"), tr("The socket is bound to an address and port."));
            break;
        case QAbstractSocket::ClosingState:
            QMessageBox::information(this, tr("Tcp Server Client"), tr("The socket is about to close."));
            break;
        case QAbstractSocket::ListeningState:
            QMessageBox::information(this, tr("Tcp Server Client"), tr("The socket is listening."));
            break;
        default:
            QMessageBox::information(this, tr("Tcp Server Client"), tr("Unknown State."));
    }
}

void Widget::onConnectionTerminated()
{
    QMessageBox::information(this, tr("Tcp Server Client"), tr("Disconnected."));
}

void Widget::onConnectionEstablished()
{
    QMessageBox::information(this, tr("Tcp Server Client"), tr("Connected!"));
}

Я был бы очень признателен, если бы кто-нибудь помог мне определить, почему эта ошибка может возникнуть. Я новичок в Qt и сети, поэтому может быть что-то довольно очевидное, что я упускаю.

Заранее спасибо!


person mtwister    schedule 25.06.2015    source источник


Ответы (2)


На самом деле есть основная вещь, которую вам не хватает: чтобы иметь возможность подключиться к сокету, вам нужен процесс, который прослушивает этот адрес и порт. Таким образом, вы можете использовать два экземпляра одного и того же программного обеспечения для установления соединения, но один из двух экземпляров должен действовать как сервер (и прослушивать), а второй экземпляр должен пытаться установить соединение. Пока вы реализовали только вторую часть.

Итак, вы должны добавить что-то вроде:

void Widget::on_listen_clicked()
{
    if (!m_socket->listen()) {
        QMessageBox::information(this, tr("Tcp Server"),tr("Error listening!"));
    }
}

И, конечно же, вам нужно иметь кнопку прослушивания на вашем виджете и использовать ее на одном из ваших запущенных экземпляров.

person Marco    schedule 26.06.2015

Вы не можете использовать широковещательный адрес с TCP. Таким образом, вы можете либо выбрать одноадресный адрес (адрес, указывающий на один пункт назначения), либо использовать адрес QUdpSocket.

Вы можете найти примеры в документации для обоих случаев: http://doc.qt.io/qt-5/examples-network.html

person alexisdm    schedule 25.06.2015
comment
Я попробовал QHostAddress::LocalHost (который, как мне кажется, является одноадресным), и у меня возникла та же проблема. Возможно, я что-то еще упускаю? Спасибо! - person mtwister; 26.06.2015
comment
Я попытался подключить два компьютера через кабель Ethernet и ввел соответствующие IP-адреса. У меня все еще та же проблема. Поэтому я предполагаю, что с моим кодом что-то еще не так... - person mtwister; 26.06.2015
comment
Вы открыли порт, к которому пытаетесь подключиться локально (для локального хоста) или на другом компьютере (например, с помощью QTcpServer и его функции listen или любого другого серверного программного обеспечения)? - person alexisdm; 26.06.2015