没有QTcpSocket的接待

时间:2018-03-13 23:30:15

标签: c++ qt tcp network-programming qtcpsocket

我到处寻找例子,我似乎无法找到解决方案。

问题

所以:我有这个名为DataReceiver的接收类。基本上,我只想从localhost(127.0.0.1)网络上的TCP套接字接收数据。看来我可以写这个socket(我用Wireshark软件检查过),但看起来程序没有收到任何东西。

我在onDataReceived QT SLOT中放置了一个qDebug()语句。此插槽似乎不会在任何时刻触发。我尝试手动编辑mTcpSocket-> readyRead()QT SIGNAL,并且正确调用了插槽,这意味着没有发出信号,因为QTcpSocket没有收到任何信息(或者至少我这样)。

我的电脑是Mac w / macOS High Sierra。我扫描了开放端口,发现51470& 50911是开放的。这些是我测试过的端口。

DataReceiver类

此课程的代码如下:

datareceiver.h:

class DataReceiver : QObject
{
    Q_OBJECT

public:
    // Con/Destructors
    explicit DataReceiver(QObject *parent = nullptr);
    explicit DataReceiver(const QString &pSourceAddress,
                          const unsigned int &pSourcePort,
                          QObject *parent = nullptr);
    ~DataReceiver();

    // Network Management
    bool connectToHost(void);

    // Getters
    QVector<float> *getData(void) const;
    QTcpSocket *getTcpSocket(void) const;
    QString getSourceAddress(void) const;
    unsigned int getSourcePort(void) const;

    // Setters
    void setData(const QVector<float> *pData);
    void setSourceAddress(const QString &pSourceAddress);
    void setSourcePort(const unsigned int &pSourcePort);

signals:

public slots:
    void onConnect();
    void onDisconnect();
    void onBytesWritten(qint64 bytes);
    void onDataReceived();

private slots:

private:
    void decodeData(const QByteArray &pMessage);

    QTcpSocket *mTcpSocket;
    QString mSourceAddress;
    unsigned int mSourcePort;

    const unsigned int mDataSize = 30;
    QVector<float> *mData;
};

并执行:datareceiver.cpp

// Con/Destructors
DataReceiver::DataReceiver(QObject *parent) :
    QObject(parent),
    mTcpSocket(new QTcpSocket(this)),
    mSourceAddress("127.0.0.1"),
    mSourcePort(51470),
    mData(new QVector<float>)
{
    for( unsigned int i = 0; i < mDataSize; i++)
        mData->append(.0);
}

DataReceiver::DataReceiver(const QString &pSourceAddress,
                      const unsigned int &pSourcePort,
                      QObject *parent) :
    QObject(parent),
    mTcpSocket(new QTcpSocket(this)),
    mSourceAddress(pSourceAddress),
    mSourcePort(pSourcePort),
    mData(new QVector<float>)
{
    for( unsigned int i = 0; i < mDataSize; i++)
        mData->append(.0);
}

DataReceiver::~DataReceiver(){
    mTcpSocket->disconnectFromHost();
    mTcpSocket->waitForDisconnected();
    delete mTcpSocket;

    delete mData;
}

// Network Management
bool DataReceiver::connectToHost(void){
    connect(mTcpSocket, SIGNAL(connected()), this, SLOT(onConnect()));
    connect(mTcpSocket, SIGNAL(disconnected()), this, SLOT(onDisconnect()));
    connect(mTcpSocket, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64)));
    connect(mTcpSocket, SIGNAL(readyRead()), this, SLOT(onDataReceived()));

    qDebug() << "connecting...";

    //emit mTcpSocket->readyRead(); // For testing. We correctly trigger the onDataReceived slot

    mTcpSocket->open(QAbstractSocket::ReadWrite);
    mTcpSocket->connectToHost(getSourceAddress(), getSourcePort());

    if(!mTcpSocket->waitForConnected(1000))
    {
        qDebug() << "Error: " << mTcpSocket->errorString();
        return false;
    }
    mTcpSocket->write("Hello ?"); // Test
    return true;
}

// Getters
QVector<float> *DataReceiver::getData(void) const{
    return mData;
}

QTcpSocket *DataReceiver::getTcpSocket(void) const{
    return mTcpSocket;
}

QString DataReceiver::getSourceAddress(void) const{
    return mSourceAddress;
}

unsigned int DataReceiver::getSourcePort(void) const{
    return mSourcePort;
}

// Setters
void DataReceiver::setData(const QVector<float> *pData){
    // Not yet implemented
    Q_UNUSED(pData);
}

void DataReceiver::setSourceAddress(const QString &pSourceAddress){
    mSourceAddress = pSourceAddress;
}

void DataReceiver::setSourcePort(const unsigned int &pSourcePort){
    mSourcePort = pSourcePort;
}

// Public Slots
void DataReceiver::onConnect(){
    qDebug() << "connected...";
}

void DataReceiver::onDisconnect(){
    qDebug() << "disconnected...";
}

void DataReceiver::onBytesWritten(qint64 bytes){
    qDebug() << bytes << " bytes written...";
}

// Private Slots
void DataReceiver::onDataReceived(){
    // Not yet implemented, code is for testing
    qDebug() << "onDataReceived called !";

    while(mTcpSocket->bytesAvailable()){
        qInfo() << mTcpSocket->read(mTcpSocket->bytesAvailable());
        qDebug() << mTcpSocket->readAll();
    }
}

// Private Methods
void DataReceiver::decodeData(const QByteArray &pMessage){
    // Not yet implemented
    Q_UNUSED(pMessage);
}

mData / mDataSize在此处供将来使用,因此在此处将被忽略。

发件人

要发送数据,我尝试使用 netcat

cat testfile.txt | nc 127.0.0.1 51470

我还创建了一个 DataSender 类,其结构与DataReceiver类相同。 根据Wireshark的说法,这两种方法似乎都是通过TCP写入数据。

DataSender类

datasender.h

class DataSender : QObject
{
    Q_OBJECT

public:
    // Con/Destructors
    explicit DataSender(QObject *parent = nullptr);
    ~DataSender();

    // Network Management
    bool connectToHost(void);
    void sendData(void) const;

    // Getters
    QString getDestinationAddress(void) const;
    unsigned int getDestinationPort(void) const;

    // Setters
    void setDestinationAddress(const QString &pDestinationAddress);
    void setDestinationPort(const unsigned int &pDestinationPort);

signals:

public slots:
    void onConnect();
    void onDisconnect();
    void onBytesWritten(qint64 bytes);
    void onDataReceived();

private:
    QTcpSocket *mTcpSocket;
    QString mDestinationAddress;
    unsigned int mDestinationPort;
};

datasender.cpp

DataSender::DataSender(QObject *parent) :
    QObject(parent),
    mTcpSocket(new QTcpSocket(this)),
    mDestinationAddress("127.0.0.1"),
    mDestinationPort(50911)
{

}

DataSender::~DataSender(){
    mTcpSocket->disconnectFromHost();
    mTcpSocket->waitForDisconnected();
    delete mTcpSocket;
}

// Network Management
bool DataSender::connectToHost(void){
    connect(mTcpSocket, SIGNAL(connected()), this, SLOT(onConnect()));
    connect(mTcpSocket, SIGNAL(disconnected()), this, SLOT(onDisconnect()));
    connect(mTcpSocket, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64)));
    connect(mTcpSocket, SIGNAL(readyRead()), this, SLOT(onDataReceived()));

    qDebug() << "connecting...";

    mTcpSocket->setSocketOption(QAbstractSocket::KeepAliveOption, true);

    mTcpSocket->connectToHost(getDestinationAddress(), getDestinationPort());

    if(!mTcpSocket->waitForConnected(1000))
    {
        qDebug() << "Error: " << mTcpSocket->errorString();
        return false;
    }
    return true;
}

void DataSender::sendData(void) const{
    QByteArray lData("Hello, this is DataSender ! Do you copy ? I repeat, do you copy ?");

    QByteArray lTemp;
    QDataStream lData2(&lTemp, QIODevice::ReadWrite);
    lData2 << lData.size();

    if(mTcpSocket->state() == QAbstractSocket::ConnectedState)
    {
        mTcpSocket->write(lTemp); //write size of data
        mTcpSocket->write(lData); //write the data itself
        mTcpSocket->waitForBytesWritten();
    }
}

// Getters
QString DataSender::getDestinationAddress(void) const{
    return mDestinationAddress;
}

unsigned int DataSender::getDestinationPort(void) const{
    return mDestinationPort;
}

// Setters
void DataSender::setDestinationAddress(const QString &pDestinationAddress){
    mDestinationAddress = pDestinationAddress;
}

void DataSender::setDestinationPort(const unsigned int &pDestinationPort){
    mDestinationPort = pDestinationPort;
}

// Public Slots
void DataSender::onConnect(){
    qDebug() << "connected...";
}

void DataSender::onDisconnect(){
    qDebug() << "disconnected...";
}

void DataSender::onBytesWritten(qint64 bytes){
    qDebug() << bytes << " bytes written...";
}

void DataSender::onDataReceived(){
    // Not yet implemented, code is for testing
    qDebug() << "onDataReceived called !";

    //while(mTcpSocket->bytesAvailable()){
        //qInfo() << mTcpSocket->read(mTcpSocket->bytesAvailable());
        //qDebug() << mTcpSocket->readAll();
    //}
}

客户端主

// Main routine ---------------------------------
int main(int argc, char **argv){

    // Initializing application.
    QApplication lApplication(argc, argv);

    CLIENT::DataReceiver dataReceiver;
    dataReceiver.connectToHost();

    return lApplication.exec();
}

服务器端主

// Main routine ---------------------------------
int main(int argc, char **argv){
    QApplication lApplication(argc, argv);

    SERVER::DataSender lDataSender;
    lDataSender.connectToHost();
    lDataSender.sendData();

    return lApplication.exec();
}

行为

基本上,当我在main中运行 DataReceiver 类时,我会得到以下行为:

connecting...
connected...
7 bytes written...       # This is the write("Hello ?") I inserted just for testing

# "connected..." may occur after "7 bytes written...", 
# I don't remember, I am not in front of my computer right now. 

结论

我相信我只是忘记了一些重要的东西,或者说有一些我不知道的东西。这是一个个人项目,所以欢迎一点外部见解!

非常感谢!

Clovel

2 个答案:

答案 0 :(得分:0)

QTcpSocket可以与另一个QTcpSocket进行通信,但为​​了实现这一点,必须使用client-server model进行初始连接。

QTcpSocket无法侦听传入连接。相反,QTcpServer可以使用(或QLocalServer,如果使用QLocalSocket)。

在传入连接的端口上将QTcpSocket设置为listen,并且在建立连接时,将发出信号以通知newConnection。调用nextPendingConnection会返回服务器端的QTcpSocket,允许它从传入连接与客户端通信。

答案 1 :(得分:0)

所以这是OP,这是我实施的解决方案。我要感谢@TheDarkKnight&amp; @ G.M。他们的澄清。

解决方案

我使用了QTcpSocket AND DataReceiver的组合,而不是QTcpSocketQTcpServer。基本上,QTcpServer会监听新的连接和建立连接时设置QTcpSocket

然后,班级只需将QTcpSocket信号readyRead()连接到个人广告位。以下是该类的实现:

DataReceiver类

datareceiver.h

class DataReceiver : QObject
{
    Q_OBJECT

public:
    // Con/Destructors
    explicit DataReceiver(QObject *parent = nullptr);
    explicit DataReceiver(const QString &pSourceAddress,
                          const unsigned int &pSourcePort,
                          QObject *parent = nullptr);
    ~DataReceiver();

    // Getters
    QVector<float> *getData(void) const;
    QTcpServer *getTcpServer(void) const;
    QString getSourceAddress(void) const;
    unsigned int getSourcePort(void) const;

    // Setters
    void setData(const QVector<float> *pData);
    void setSourceAddress(const QString &pSourceAddress);
    void setSourcePort(const unsigned int &pSourcePort);

signals:

public slots:
    void onConnect();
    void onDisconnect();
    void onBytesWritten(qint64 bytes);
    void onDataReceived();
    void onNewConnection();

private:
    void decodeData(const QByteArray &pMessage);

    QTcpServer *mTcpServer;
    QTcpSocket *mTcpSocket;
    QString mSourceAddress;
    unsigned int mSourcePort;

    const unsigned int mDataSize = 30;
    QVector<float> *mData;
};

datareceiver.cpp

// Con/Destructors
DataReceiver::DataReceiver(QObject *parent) :
    QObject(parent),
    mTcpServer(new QTcpServer(this)),
    mSourceAddress("127.0.0.1"),
    mSourcePort(51470),
    mData(new QVector<float>)
{
    for( unsigned int i = 0; i < mDataSize; i++)
        mData->append(.0);

    connect(mTcpServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));

    if(!mTcpServer->listen(QHostAddress(getSourceAddress()), getSourcePort()))
        qDebug() << "<DataReceiver> Server could not start. ";
    else
        qDebug() << "<DataReceiver> Server started !";
}

DataReceiver::DataReceiver(const QString &pSourceAddress,
                      const unsigned int &pSourcePort,
                      QObject *parent) :
    QObject(parent),
    mTcpServer(new QTcpServer(this)),
    mSourceAddress(pSourceAddress),
    mSourcePort(pSourcePort),
    mData(new QVector<float>)
{
    for( unsigned int i = 0; i < mDataSize; i++)
        mData->append(.0);

    connect(mTcpServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));

    if(!mTcpServer->listen(QHostAddress(getSourceAddress())), getSourcePort())
        qDebug() << "<DataReceiver> Server could not start. ";
    else
        qDebug() << "<DataReceiver> Server started !";

}

DataReceiver::~DataReceiver(){
    delete mTcpServer;

    delete mData;
}

// Getters
QVector<float> *DataReceiver::getData(void) const{
    return mData;
}

QTcpServer *DataReceiver::getTcpServer(void) const{
    return mTcpServer;
}

QString DataReceiver::getSourceAddress(void) const{
    return mSourceAddress;
}

unsigned int DataReceiver::getSourcePort(void) const{
    return mSourcePort;
}

// Setters
void DataReceiver::setData(const QVector<float> *pData){
    // Not yet implemented
    Q_UNUSED(pData);
}

void DataReceiver::setSourceAddress(const QString &pSourceAddress){
    mSourceAddress = pSourceAddress;
}

void DataReceiver::setSourcePort(const unsigned int &pSourcePort){
    mSourcePort = pSourcePort;
}

// Public Slots
void DataReceiver::onConnect(){
    qDebug() << "QTcpSocket connected...";
}

void DataReceiver::onDisconnect(){
    qDebug() << "QTcpSocket disconnected...";
    disconnect(mTcpSocket, SIGNAL(readyRead()), this, SLOT(onDataReceived()));
    disconnect(mTcpSocket, SIGNAL(disconnected()), this, SLOT(onDisconnect()));
}

void DataReceiver::onBytesWritten(qint64 bytes){
    qDebug() << bytes << " bytes written to QTcpSocket...";
}

void DataReceiver::onDataReceived(){
    // Not yet implemented, code is for testing
    qDebug() << "onDataReceived called !";

    while(mTcpSocket->bytesAvailable()){
        qInfo() << mTcpSocket->read(mTcpSocket->bytesAvailable());
        qDebug() << mTcpSocket->readAll();
    }
}

void DataReceiver::onNewConnection(){
    qDebug() << "onNewConnection called !";
    mTcpSocket = mTcpServer->nextPendingConnection();

    connect(mTcpSocket, SIGNAL(readyRead()),    this, SLOT(onDataReceived()));
    connect(mTcpSocket, SIGNAL(disconnected()), this, SLOT(onDisconnect()));
}

// Private Methods
void DataReceiver::decodeData(const QByteArray &pMessage){
    // Not yet implemented
    Q_UNUSED(pMessage);
}