没有 QTcpSocket 接收
Posted
技术标签:
【中文标题】没有 QTcpSocket 接收【英文标题】:No reception w/ QTcpSocket 【发布时间】:2018-03-13 23:30:15 【问题描述】:我到处寻找示例,但似乎找不到解决方案。
问题
所以:我有一个名为 DataReceiver 的接收类。基本上,我只想从 localhost (127.0.0.1) 网络上的 TCP 套接字接收数据。似乎我可以用这个套接字编写(我用 Wireshark 软件检查过),但看起来程序没有收到任何东西。
我在 onDataReceived QT SLOT 中放置了一个 qDebug() 语句。这个插槽似乎不会在任何时候触发。我尝试手动编辑 mTcpSocket->readyRead() QT SIGNAL,并且正确调用了插槽,这意味着没有发出信号,因为 QTcpSocket 没有收到任何东西(或者至少我是这样)。
我的电脑是带有 macOS High Sierra 的 Mac。我扫描了开放的端口,发现 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.
结论
我相信我只是忘记了一些重要的事情,或者有些事情我不知道。这是一个个人项目,所以欢迎一些外部见解!
非常感谢!
丁香
【问题讨论】:
您的代码中是否运行了事件循环?发送数据是一回事,但您没有包括发送给您的服务器部分。你的客户端类在我看来没问题。 有了这段代码,即使我有问题// QTcpSocket 绑定到QHostAdress
而不是字符串?
嗨@user3606329。认为 qApplication 是“while(1)”例程,但也许不是。我需要检查带有 while(true) 循环的类的行为,看看它是否改变了任何东西。服务器/发送器部分由像这样的 DataSender 类或 netcat 命令播放。嗨 Mohammad,QTcpSocket 有几个构造函数,您指的是其中之一。其中有:QTcpSocket(const QString& Address, const int& port) QTcpSocket(const QHostAddress& Address)。顺便说一句,QHostAddress 的一个构造函数接受 QString 和 int 作为参数。
除了这里的问题之外,是否有特定原因使用 TCP over 127.0.0.1,而不是 QLocalSocket
?
嗨@TheDarkKnight。有:我不知道 QLocalSocket 存在。并且在不久的将来(不是那么快),另一个 IP 地址将取代“localhost”。
【参考方案1】:
QTcpSocket 可以与另一个 QTcpSocket
通信,但为了实现这一点,必须使用 client-server model 建立初始连接。
QTcpSocket
无法侦听传入连接。相反,可以使用QTcpServer
(或QLocalServer,如果使用QLocalSocket)。
QTcpSocket
在用于传入连接的端口上设置为listen,当建立连接时,将发出信号通知newConnection。调用nextPendingConnection 为服务器端返回QTcpSocket
,允许它通过传入连接与客户端通信。
【讨论】:
非常感谢您的澄清!我实现了一个 QTcpServer,它确实有效!我使用与以前相同的方法对其进行了测试:netcat
和我编写的DataSender
类。【参考方案2】:
所以这是 OP,这是我实施的解决方案。我要感谢@TheDarkKnight 和@G.M。为了他们的澄清。
解决方案
我的DataReceiver
类没有使用QTcpSocket
,而是使用QTcpSocket
的组合AND QTcpServer
。基本上,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);
【讨论】:
以上是关于没有 QTcpSocket 接收的主要内容,如果未能解决你的问题,请参考以下文章