Hi,
I have written a server/client, initially using the Fortune examples. The data received is a QVariant - so the QVariant type can be used to determine what to do with the data.
Apologies if my explanations are not great - I am not great with describing what I want to do/have done in programming-speak.
For e.g. a QString it works fine (I guess as it comes in one block?). however attempting with a QImage -> the version/description/data type are sent OK --> If I output the emit_message in read_client then it outputs these OK. I assume this is because the images are larger and need to be sent in multiple blocks. Hence I believe the readClient() would be called multiple times for the same serialized data item. I can't work out how to deal with this gracefully - should I create some function to deal with whether this is a fresh readClient() or one to deal with data that is mid-transmission?
Either that, or I need some sort of loop based on data/the size sent in the header, to build up "data" from the blocks/packets received but am unsure of how to go about doing this. I also send an end of data flag - could this also be used? I have looked through the forums - there are multiple issues on this topic, but I could not find a specific answer (well not with the search terms I have been using)...
Any help would be much appreciated (as well as any pointers if my code is poor -> I am a bit of a QT noob)..
Here is a stripped down version of the codes.
Server:
void Server::incomingConnection(int socketId) {
ServerSocket *socket = new ServerSocket(this);
socket->setSocketDescriptor(socketId);
}
{
connect(this, SIGNAL(readyRead()), this, SLOT(readClient()));
connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater()));
blockSize = 0;
}
void ServerSocket::readClient()
{
if (blockSize == 0) {
if (bytesAvailable() < (sizeof(quint16)))
return;
in >> blockSize;
}
if (bytesAvailable() < (quint16)(blockSize + sizeof(quint16) + sizeof(quint8)))
return;
quint8 version;
quint16 endFlag;
in >> version;
in >> description;
in >> data;
in >> endFlag;
"\n\tType(" + QString(data.
typeName()) + "): " + QString::number(data.
type()) + "\n\tSize: " + QString::number(blockSize
) + "\n\tMessage: " + description +
"\n\tData: " + data.toString() +
"\n\tEndFlag: " + QString::number(endFlag
);
}
void Server::incomingConnection(int socketId) {
ServerSocket *socket = new ServerSocket(this);
socket->setSocketDescriptor(socketId);
}
ServerSocket::ServerSocket(QObject *parent) : QTcpSocket(parent)
{
connect(this, SIGNAL(readyRead()), this, SLOT(readClient()));
connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater()));
blockSize = 0;
}
void ServerSocket::readClient()
{
QDataStream in(this);
in.setVersion(QDataStream::Qt_4_5);
if (blockSize == 0) {
if (bytesAvailable() < (sizeof(quint16)))
return;
in >> blockSize;
}
if (bytesAvailable() < (quint16)(blockSize + sizeof(quint16) + sizeof(quint8)))
return;
quint8 version;
QString description;
QVariant data;
quint16 endFlag;
in >> version;
in >> description;
in >> data;
in >> endFlag;
QString emit_message = "\n\tVersion: " + QString::number(version) +
"\n\tType(" + QString(data.typeName()) + "): " + QString::number(data.type()) +
"\n\tSize: " + QString::number(blockSize) +
"\n\tMessage: " + description +
"\n\tData: " + data.toString() +
"\n\tEndFlag: " + QString::number(endFlag);
}
To copy to clipboard, switch view to plain text mode
client:
//this is fired on the click of a QPushButton
void Client::sendRequest()
{
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(TIMEOUT)) {
emit error(socket.error(), socket.errorString());
return;
}
//text is set in a QLineEdit
if (text == "image") {
data
= QImage("someimage.jpg");
description = "This is an image";
}
else {
data = text;
description = "This is some text";
}
out << quint16(0) << quint8(1) << description << data << quint16(0xFFFF);
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16) - sizeof(quint8) - sizeof(quint16));
socket.write(block);
socket.flush();
qDebug() << "Sending: [" + description + data.toString()
+ "] to server(" + serverName
+ ":" + QString::number(serverPort
) + ")";
}
//this is fired on the click of a QPushButton
void Client::sendRequest()
{
QTcpSocket socket;
socket.connectToHost(serverName, serverPort);
if (!socket.waitForConnected(TIMEOUT)) {
emit error(socket.error(), socket.errorString());
return;
}
QVariant data;
QString description;
//text is set in a QLineEdit
if (text == "image") {
data = QImage("someimage.jpg");
description = "This is an image";
}
else {
data = text;
description = "This is some text";
}
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_5);
out << quint16(0) << quint8(1) << description << data << quint16(0xFFFF);
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16) - sizeof(quint8) - sizeof(quint16));
socket.write(block);
socket.flush();
qDebug() << "Sending: [" + description + data.toString()
+ "] to server(" + serverName + ":" + QString::number(serverPort) + ")";
}
To copy to clipboard, switch view to plain text mode
Thanks,
James
Bookmarks