aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNils Jeisecke <nils.jeisecke@saltation.com>2021-05-31 15:23:18 +0200
committerNils Jeisecke <nils.jeisecke@saltation.com>2021-05-31 16:12:32 +0200
commit0c458ec8c96d15f96947f1fe401654a903152a72 (patch)
tree4baf50476e034ba116dbc7819cbfbac7d59e4ed9
parentMerge pull request #132 from itay-grudev/removed_incorrect_coment_in_basic_ex... (diff)
downloadsingleapplication-0c458ec8c96d15f96947f1fe401654a903152a72.tar.xz
Add simple acknowledge protocol to ensure the server has received all data
The server now acknowledges every received message by sending a \r. By waiting for the acknowledgement, clients should no longer terminate too early, causing bytes getting lost in Qt's internal socket handling. Message handling in the server is simplified because we can now rely on the readyRead signal being raised for every frame. This should finally solve #125 and #121. What remains is to correctly handle data sent using SingleApplication::sendMessage.
-rw-r--r--singleapplication.cpp5
-rw-r--r--singleapplication_p.cpp38
-rw-r--r--singleapplication_p.h2
3 files changed, 31 insertions, 14 deletions
diff --git a/singleapplication.cpp b/singleapplication.cpp
index 7e153a0..09e264e 100644
--- a/singleapplication.cpp
+++ b/singleapplication.cpp
@@ -248,10 +248,7 @@ bool SingleApplication::sendMessage( const QByteArray &message, int timeout )
if( ! d->connectToPrimary( timeout, SingleApplicationPrivate::Reconnect ) )
return false;
- d->socket->write( message );
- bool dataWritten = d->socket->waitForBytesWritten( timeout );
- d->socket->flush();
- return dataWritten;
+ return d->writeConfirmedMessage( timeout, message );
}
/**
diff --git a/singleapplication_p.cpp b/singleapplication_p.cpp
index 27b688f..365799e 100644
--- a/singleapplication_p.cpp
+++ b/singleapplication_p.cpp
@@ -272,11 +272,31 @@ bool SingleApplicationPrivate::connectToPrimary( int msecs, ConnectionType conne
#endif
headerStream << static_cast <quint64>( initMsg.length() );
- socket->write( header );
- socket->write( initMsg );
- bool result = socket->waitForBytesWritten( static_cast<int>(msecs - time.elapsed()) );
+ if( !writeConfirmedMessage( static_cast<int>(msecs - time.elapsed()), header ) )
+ return false;
+
+ if( !writeConfirmedMessage( static_cast<int>(msecs - time.elapsed()), initMsg ) )
+ return false;
+
+ return true;
+}
+
+void SingleApplicationPrivate::writeAck( QLocalSocket *sock ) {
+ sock->putChar('\n');
+}
+
+bool SingleApplicationPrivate::writeConfirmedMessage( int msecs, const QByteArray &msg )
+{
+ socket->write( msg );
socket->flush();
- return result;
+
+ bool result = socket->waitForReadyRead( msecs ); // await ack byte
+ if (result) {
+ socket->read( 1 );
+ return true;
+ }
+
+ return false;
}
quint16 SingleApplicationPrivate::blockChecksum() const
@@ -379,9 +399,7 @@ void SingleApplicationPrivate::readInitMessageHeader( QLocalSocket *sock )
info.stage = StageBody;
info.msgLen = msgLen;
- if ( sock->bytesAvailable() >= (qint64) msgLen ){
- readInitMessageBody( sock );
- }
+ writeAck( sock );
}
void SingleApplicationPrivate::readInitMessageBody( QLocalSocket *sock )
@@ -448,15 +466,15 @@ void SingleApplicationPrivate::readInitMessageBody( QLocalSocket *sock )
Q_EMIT q->instanceStarted();
}
- if (sock->bytesAvailable() > 0){
- this->slotDataAvailable( sock, instanceId );
- }
+ writeAck( sock );
}
void SingleApplicationPrivate::slotDataAvailable( QLocalSocket *dataSocket, quint32 instanceId )
{
Q_Q(SingleApplication);
Q_EMIT q->receivedMessage( instanceId, dataSocket->readAll() );
+
+ writeAck( dataSocket );
}
void SingleApplicationPrivate::slotClientConnectionClosed( QLocalSocket *closedSocket, quint32 instanceId )
diff --git a/singleapplication_p.h b/singleapplication_p.h
index c49a46d..0777c33 100644
--- a/singleapplication_p.h
+++ b/singleapplication_p.h
@@ -81,6 +81,8 @@ public:
QString primaryUser() const;
void readInitMessageHeader(QLocalSocket *socket);
void readInitMessageBody(QLocalSocket *socket);
+ bool writeConfirmedMessage(int msecs, const QByteArray &msg);
+ void writeAck(QLocalSocket *sock);
static void randomSleep();
void addAppData(const QString &data);
QStringList appData() const;