我正在使用QTCPSockets与我在Qt for Raspberry Pi中编写的程序交谈。相同的软件在我的Mac(或Windows,无论如何)上运行。 Pi正在运行QTCPServer。
我向它发送JSON数据,大部分时间都可以。
但有时,Pi没有响应,数据似乎没有到来。但是,当我发送更多数据时,该数据未被处理,但之前的Json消息是!而这就像这样。所有消息现在都关闭1.发送新消息,触发前一个消息。
感觉与此错误报告有点联系:https://bugreports.qt.io/browse/QTBUG-58262 但我不确定它是否相同。
我已经尝试了waitForBytesWritten
和flush
,它似乎最初起作用,但后来我又看到了这个问题。
我希望Pi上的TCP缓冲区没有被刷新,但我现在知道如何确保立即处理所有数据。
如所问,这是一些源代码: 这是客户端软件:
Client::Client() : tcpSocket(new QTcpSocket(this)), in(tcpSocket)
{
connect(tcpSocket, &QIODevice::readyRead, this, &Client::readData);
connect(tcpSocket, &QTcpSocket::connected, this, &Client::connected);
connect(tcpSocket, &QTcpSocket::stateChanged, this, &Client::onConnectionStateChanged);
void (QAbstractSocket:: *sig)(QAbstractSocket::SocketError) = &QAbstractSocket::error;
connect(tcpSocket, sig, this, &Client::error);
}
void Client::connectTo(QString ip, int port) {
this->ip = ip;
this->port = port;
tcpSocket->connectToHost(ip, port);
}
void Client::reconnect() {
connectTo(ip, port);
}
void Client::disconnect()
{
tcpSocket->disconnectFromHost();
}
void Client::connected()
{
qDebug() << TAG << "connected!";
}
void Client::error(QAbstractSocket::SocketError error)
{
qDebug() << TAG << error;
}
void Client::sendData(const QString& data)
{
bool connected = (tcpSocket->state() == QTcpSocket::ConnectedState);
if (!connected) {
qDebug() << TAG << "NOT CONNECTED!";
return;
}
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_7);
out << data;
tcpSocket->write(block);
tcpSocket->flush();
}
void Client::sendData(const QByteArray& data) {
bool connected = (tcpSocket->state() == QTcpSocket::ConnectedState);
if (!connected) {
qDebug() << TAG << " is NOT connected!";
return;
}
tcpSocket->write(data);
tcpSocket->flush();
}
void Client::readData()
{
in.startTransaction();
QString data;
in >> data;
if (!in.commitTransaction())
{
return;
}
emit dataReceived(data);
}
void Client::onConnectionStateChanged(QAbstractSocket::SocketState state)
{
switch (state) {
case QAbstractSocket::UnconnectedState:
connectionState = "Not connected";
break;
case QAbstractSocket::ConnectingState:
connectionState = "connecting";
break;
case QAbstractSocket::ConnectedState:
connectionState = "connected";
break;
default:
connectionState = QString::number(state);
}
qDebug() << TAG << " connecting state: " << state;
emit connectionStateChanged(connectionState);
if (state == QAbstractSocket::UnconnectedState) {
QTimer::singleShot(1000, this, &Client::reconnect);
}
}
这里是服务器部分:
Server::Server()
{
tcpServer = new QTcpServer(this);
connect(tcpServer, &QTcpServer::newConnection, this, &Server::handleConnection);
tcpServer->listen(QHostAddress::Any, 59723);
QString ipAddress;
QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
// use the first non-localhost IPv4 address
for (int i = 0; i < ipAddressesList.size(); ++i) {
if (ipAddressesList.at(i) != QHostAddress::LocalHost &&
ipAddressesList.at(i).toIPv4Address()) {
ipAddress = ipAddressesList.at(i).toString();
break;
}
}
// if we did not find one, use IPv4 localhost
if (ipAddress.isEmpty())
ipAddress = QHostAddress(QHostAddress::LocalHost).toString();
qDebug() << TAG << "ip " << ipAddress << " serverport: " << tcpServer->serverPort();
}
void Server::clientDisconnected()
{
QTcpSocket *client = qobject_cast<QTcpSocket *>(QObject::sender());
int idx = clients.indexOf(client);
if (idx != -1) {
clients.removeAt(idx);
}
qDebug() << TAG << "client disconnected: " << client;
client->deleteLater();
}
void Server::handleConnection()
{
qDebug() << TAG << "incoming!";
QTcpSocket* clientConnection = tcpServer->nextPendingConnection();
connect(clientConnection, &QAbstractSocket::disconnected, this, &Server::clientDisconnected);
connect(clientConnection, &QIODevice::readyRead, this, &Server::readData);
clients.append(clientConnection);
broadcastUpdate(Assets().toJson());
}
void Server::readData()
{
QTcpSocket *client = qobject_cast<QTcpSocket *>(QObject::sender());
QDataStream in(client);
in.startTransaction();
QString data;
in >> data;
if (!in.commitTransaction())
{
return;
}
...
// here I do something with the data. I removed that code as it is
// not necessary for this issue
...
broadcastUpdate(data);
}
void Server::broadcastUpdate(const QString& data)
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_7);
out << data;
foreach(QTcpSocket* client, clients) {
bool connected = (client->state() == QTcpSocket::ConnectedState);
if (!connected) {
qDebug() << TAG << client << " is NOT connected!";
continue;
}
client->write(block);
}
}
答案 0 :(得分:2)
我认为问题出在您的void Client::readData()
上:您必须以这样的方式编写它,以便从其中的套接字读取所有可用数据(通常用while (socket->bytesAvailable() > 0) { ... }
编写循环)。
这是因为发出readyRead()
信号的方式:远程对等体可能会向您发送任何非零数量的数据包,并且您的套接字将发出任何非零数量的readyRead()
信号。在您的情况下,似乎服务器发送两条消息,但它们只会导致在客户端上发出一个readyRead()
信号。