1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
#include "blockingsocketprivate.h"
#include <QTcpSocket>
#include <QCoreApplication>
#include <QTimer>
#include <QThread>
BlockingSocketPrivate::BlockingSocketPrivate()
{
}
BlockingSocketPrivate::~BlockingSocketPrivate()
{
}
void BlockingSocketPrivate::setError(QAbstractSocket::SocketError errorCode, const QString& errMsg)
{
this->errorCode = errorCode;
this->errorText = errMsg;
}
bool BlockingSocketPrivate::isConnected()
{
return (socket && socket->isOpen() && socket->state() == QAbstractSocket::ConnectedState);
}
QAbstractSocket::SocketError BlockingSocketPrivate::getErrorCode()
{
return errorCode;
}
void BlockingSocketPrivate::createSocketIfNecessary()
{
// This method is called only when the socket is already called,
// so we're sure the socket is created in the target thread.
if (socket)
return;
socket = new QTcpSocket(this);
connect(socket, SIGNAL(disconnected()), this, SIGNAL(disconnected()));
}
QString BlockingSocketPrivate::getErrorText()
{
return errorText;
}
void BlockingSocketPrivate::handleSendCall(const QByteArray& bytes, bool& result)
{
createSocketIfNecessary();
result = true;
qint64 size = bytes.size();
qint64 totalBytesSent = 0;
qint64 bytesSent = 0;
while (totalBytesSent < size)
{
bytesSent = socket->write(totalBytesSent == 0 ? bytes : bytes.mid(totalBytesSent));
if (bytesSent < 0)
{
result = false;
setError(socket->error(), socket->errorString());
return;
}
totalBytesSent += bytesSent;
}
}
void BlockingSocketPrivate::handleReadCall(qint64 count, int timeout, QByteArray& resultBytes, bool& result)
{
createSocketIfNecessary();
resultBytes.clear();
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
QTimer timer;
timer.setSingleShot(true);
timer.setInterval(timeout);
timer.start();
while (resultBytes.size() < count && timer.isActive())
{
if (!isConnected())
{
qWarning() << "Blocking socket closed in the middle of reading.";
result = false;
setError(socket->error(), socket->errorString());
return;
}
if (socket->bytesAvailable() == 0)
{
QThread::msleep(1);
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
continue;
}
resultBytes += socket->read(qMin(socket->bytesAvailable(), count));
}
result = (resultBytes.size() >= count && timer.isActive());
}
void BlockingSocketPrivate::handleConnectCall(const QString& host, int port, bool& result)
{
result = true;
if (isConnected())
return;
createSocketIfNecessary();
socket->connectToHost(host, port);
if (!socket->waitForConnected())
{
result = false;
setError(socket->error(), socket->errorString());
}
}
void BlockingSocketPrivate::handleDisconnectCall()
{
if (!isConnected())
return;
createSocketIfNecessary();
socket->abort();
socket->close();
}
void BlockingSocketPrivate::handleIsConnectedCall(bool& connected)
{
connected = isConnected();
}
|