【发布时间】:2018-09-01 09:12:03
【问题描述】:
我来这里是为了就我的项目中的一个奇怪行为寻求帮助。就这样吧!
问题
我有一个名为 DataReceiver 的接收类,它使用一个 QTcpServer 和一个 QTcpSocket,并且我有一个 DataSender 类通过 QTcpSocket 为其提供数据。我定期发送数据,并使用 QTimer 触发“发送”插槽。
但是,经过几次迭代,提要停止,不再是周期性的。我真的不明白发生了什么。
我已确认此问题与接收方的终端打印有关。
代码
datasender.cpp
// Con/Destructors
DataSender::DataSender(QObject *parent) :
QObject(parent),
mTcpSocket(new QTcpSocket(this)),
mDestinationAddress("127.0.0.1"),
mDestinationPort(51470),
mTimer(new QTimer(this))
{
connectToHost();
connect(mTimer, SIGNAL(timeout(void)), this, SLOT(sendPeriodicData()));
mTimer->start(1000);
}
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)));
qDebug() << "connecting...";
mTcpSocket->setSocketOption(QAbstractSocket::KeepAliveOption, true);
mTcpSocket->setSocketOption(QAbstractSocket::WriteOnly);
mTcpSocket->connectToHost(getDestinationAddress(), getDestinationPort());
if(!mTcpSocket->waitForConnected(1000))
{
qDebug() << "Error: " << mTcpSocket->errorString();
return false;
}
// Setting meteo data to send
mMeteoData.messageID = METEO_MESSAGE;
mMeteoData.temperature = 5.5;
mMeteoData.pressure = 10.2;
mMeteoData.humidity = 45.5;
// Setting positiondata to send
mPositionData.messageID = POSITION_MESSAGE;
mPositionData.north = 120.3;
mPositionData.pitch = 1.5;
mPositionData.roll = 2.5;
mPositionData.yaw = 3.5;
mPositionData.a_x = 30.5;
mPositionData.a_y = 40.5;
mPositionData.a_z = 50.5;
return true;
}
void DataSender::sendData(void) const{
QByteArray lData("Hello, this is DataSender ! Do you copy ? I repeat, do you copy ?");
if(mTcpSocket->state() == QAbstractSocket::ConnectedState)
{
mTcpSocket->write(lData);
mTcpSocket->waitForBytesWritten();
}
}
void DataSender::sendData(const QByteArray &pData) const{
//QByteArray lData("Hello, this is DataSender ! Do you copy ? I repeat, do you copy ?");
if(mTcpSocket->state() == QAbstractSocket::ConnectedState)
{
mTcpSocket->write(pData);
mTcpSocket->waitForBytesWritten();
mTcpSocket->flush();
//usleep(1000);
}
}
// 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::sendPeriodicData(void){
mTcpSocket->
// Changing data for testing
mPositionData.north += 10;
mPositionData.north = std::fmod(mPositionData.north, 360);
mMeteoData.temperature += 10;
mMeteoData.temperature = std::fmod(mMeteoData.temperature, 500);
// Declaring QByteArrays
QByteArray lMeteoByteArray;
QByteArray lPositionByteArray;
// Serializing
lMeteoByteArray = serializeMeteoData(mMeteoData);
lPositionByteArray = serializePositionData(mPositionData);
// Sending
sendData(lMeteoByteArray);
sendData(lPositionByteArray);
}
datareceiver.cpp
// Con/Destructors
DataReceiver::DataReceiver(QObject *parent) :
QObject(parent),
mTcpServer(new QTcpServer(this)),
mSourceAddress("127.0.0.1"),
mSourcePort(51470)
{
initData();
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)
{
initData();
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(){
if(mTcpSocket != nullptr) delete mTcpSocket;
delete mTcpServer;
if(mTcpSocket != nullptr)
delete mTcpSocket;
}
// Getters
QTcpServer *DataReceiver::getTcpServer(void) const{
return mTcpServer;
}
QString DataReceiver::getSourceAddress(void) const{
return mSourceAddress;
}
unsigned int DataReceiver::getSourcePort(void) const{
return mSourcePort;
}
positionData_t DataReceiver::getPositionData(void) const{
return mPositionData;
}
meteoData_t DataReceiver::getMeteoData(void) const{
return mMeteoData;
}
// Setters
void DataReceiver::setSourceAddress(const QString &pSourceAddress){
mSourceAddress = pSourceAddress;
}
void DataReceiver::setSourcePort(const unsigned int &pSourcePort){
mSourcePort = pSourcePort;
}
void DataReceiver::setPositionData(const positionData_t &pPositionData){
mPositionData = pPositionData;
}
void DataReceiver::setMeteoData(const meteoData_t &pMeteoData){
mMeteoData = pMeteoData;
}
// Data Management
void DataReceiver::initPositionData(void){
mPositionData.messageID = METEO_MESSAGE;
mPositionData.pitch = .0;
mPositionData.roll = .0;
mPositionData.yaw = .0;
mPositionData.a_x = .0;
mPositionData.a_y = .0;
mPositionData.a_z = .0;
}
void DataReceiver::initMeteoData(void){
mMeteoData.messageID = POSITION_MESSAGE;
mMeteoData.temperature = .0;
mMeteoData.humidity = .0;
mMeteoData.pressure = .0;
}
void DataReceiver::initData(void){
initPositionData();
initMeteoData();
}
void DataReceiver::reinitData(void){
initData();
}
// 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 !";
QByteArray lReceivedData;
while(mTcpSocket->bytesAvailable()){
lReceivedData = mTcpSocket->read(mTcpSocket->bytesAvailable());
decodeData(lReceivedData);
qDebug() << lReceivedData << "\n";
}
}
void DataReceiver::onNewConnection(){
qDebug() << "onNewConnection called !";
mTcpSocket = mTcpServer->nextPendingConnection();
mTcpSocket->setSocketOption(QAbstractSocket::ReadOnly, true);
connect(mTcpSocket, SIGNAL(readyRead()), this, SLOT(onDataReceived()));
connect(mTcpSocket, SIGNAL(disconnected()), this, SLOT(onDisconnect()));
}
void DataReceiver::onDataChanged(void){
qDebug() << "onDataChanged called !";
qDebug() << "\nPrinting mMeteoData : ";
qDebug() << "mMeteoData.messageID" << mMeteoData.messageID;
qDebug() << "mMeteoData.temperature" << mMeteoData.temperature;
qDebug() << "mMeteoData.humidity" << mMeteoData.humidity;
qDebug() << "mMeteoData.pressure" << mMeteoData.pressure;
qDebug() << "\nPrinting mPositionData";
qDebug() << "mPositionData.messageID" << mPositionData.messageID;
qDebug() << "mPositionData.north" << mPositionData.north;
qDebug() << "mPositionData.pitch" << mPositionData.pitch;
qDebug() << "mPositionData.roll" << mPositionData.roll;
qDebug() << "mPositionData.yaw" << mPositionData.yaw;
qDebug() << "mPositionData.a_x" << mPositionData.a_x;
qDebug() << "mPositionData.a_y" << mPositionData.a_y;
qDebug() << "mPositionData.a_z" << mPositionData.a_z;
}
// Private Methods
void DataReceiver::decodeData(const QByteArray &pMessage){
// Not yet implemented
quint8 tempMessageID = fetchMessageID(pMessage);
switch(tempMessageID){
case UNKNOWN_MESSAGE:
break;
case METEO_MESSAGE:
mMeteoData = deserializeMeteoData(pMessage);
emit dataChanged();
break;
case POSITION_MESSAGE:
mPositionData = deserializePositionData(pMessage);
emit dataChanged();
break;
}
return;
}
更多信息
- 我发送两种类型的数据,都来自结构。在接收端,我对数据进行解码、识别并设置相应的属性。
- 接收器类用于 QT GUI 应用程序。它不是特别螺纹。我真的不知道是否有必要,因为在开始时,数据是按预期定期接收的。
结论
我真的很想为此找到解决方案...我尝试了一些无济于事的方法,例如更改读取套接字的方式或使用 QTcpSocket::flush() 方法(不确定它是否符合我的想法)
非常感谢, 丁香
奖金
我还希望能够打开 de Receiver 端并让发送方自动检测它并开始向接收方发送数据。我需要对此进行深入研究,但是如果您有小费,我们将不胜感激!
【问题讨论】:
-
void DataSender::sendPeriodicData(void){ mTcpSocket->???? -
不要使用任何
waitFor方法。那是你的问题。你不需要冲洗或做任何其他魔法。编写异步代码,让事件循环运行。不要阻挡。世界是异步的。你越假装它不是,代码就变得越意大利面,你就会有更多的错误(恕我直言)。 -
我的错误@eyllanesc,一定是^C ^V 错字。
-
感谢@KubaOber 的建议,今晚我会测试一下。我会及时通知你
-
嗨,久等了,自从我提出这个问题后,我就没有参与过这个项目。 @KubaOber 很高兴宣布删除
waitForBytesWritten并不能解决停滞问题。
标签: c++ qt tcp qtcpsocket qtcpserver