Tcp клиент Qt C ++ с витым сервером Python - PullRequest
2 голосов
/ 24 октября 2010

Я пытаюсь соединить очень простой витой сервер "hello world" с базовым tcp-клиентом Qt.

Клиент использует эти сигналы:

connect(&socket, SIGNAL(connected()), this, SLOT(startTransfer()));
connect(&socket, SIGNAL(readyRead()), this, SLOT(readServer()));

, а затем readServer () выглядит следующим образом:

ui->resultLabel->setText("Reading..");
QDataStream in(&socket);
//in.setVersion(QT_4_0);

if (blockSize == 0) {
    if (socket.bytesAvailable() < (int)sizeof(quint16))
        return;

    in >> blockSize;
}

if (socket.bytesAvailable() < blockSize)
    return;

QString theResult;
in >> theResult;
qDebug() << in;
qDebug() << theResult;
ui->resultLabel->setText(theResult);

Сервер, который я использую для тестирования, является просто примером, извлеченным из документов Twisted

from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor

### Protocol Implementation

# This is just about the simplest possible protocol
class Echo(Protocol):
    def dataReceived(self, data):
        """
        As soon as any data is received, write it back.
        """
        self.transport.write(data)


def main():
    f = Factory()
    f.protocol = Echo
    reactor.listenTCP(8000, f)
    reactor.run()

if __name__ == '__main__':
    main()

readServer () вызывается просто отлично, но кажется, что он никогда не собирает никаких данных. Я где-то читал, что это может быть связано с оператором << QDataStream, потому что python не совсем отправляет его по частям, как ожидает Qt. </p>

Я признаю, что я не очень разбираюсь в C ++ или Qt, но идея проекта - написать клиент для работы с существующим витым сервером, поэтому, пока клиент может быть изменен, у меня не остается выбора, кроме как чтобы заставить его работать с этим сервером.

Заранее спасибо за любую помощь.

Ответы [ 2 ]

2 голосов
/ 25 октября 2010

Оказалось, что проблема связана с QDataStream, который, по-видимому, является чем-то большим, чем просто небольшая информация о данных, которые он читает.

К счастью, я обнаружил QDataStream :: readRawData, который намного лучше любил данные, отправляемые python (далее я обнаружил, что это не имеет ничего общего с витой, но самой реализацией сокета python.) Окончательный код выглядел так:

//use socket to construct a QDataStream object, like before
QDataStream in(&socket); 
//in.setVersion(QDataStream::Qt_4_0);
char buffer[1024] = {0};
//readRawData takes a char to dump to and the length, 
//so I'm sure there is a better way to do this. It worked for my example.
in.readRawData(buffer, socket.bytesAvailable()); 
QString result;
result = buffer;
ui->resultLabel->setText(result);
1 голос
/ 25 октября 2010

Важно понимать, что TCP не является транспортным средством для сообщений (или «кусков») определенного размера. Это транспорт для потока байтов. Когда вы пишете что-то вроде:

if (socket.bytesAvailable() < (int)sizeof(quint16))
    return;

тогда вам лучше где-нибудь создать цикл, который снова вызывает этот код, потому что нет гарантии, что в первый раз вы получите все байты, необходимые для прохождения этой проверки.

Вы не поделились ни одним из кода, отвечающего за отправку данных на эхо-сервер, поэтому невозможно на самом деле узнать, почему ваш клиент Qt не получает данные, которые вы ожидаете получить, но, учитывая вышесказанное, я бы не стал Не удивляйтесь, если это связано с неправильной буферизацией неполных данных.

Убедитесь, что если вы решите не читать данные из сокета из-за недостатка данных, попробуйте прочитать их снова позже, после того, как может появиться больше данных. Хороший способ сделать это состоит в том, чтобы фактически всегда считывать данные в буфер приложения, чтобы вы могли использовать select () или epoll () или что вам нужно сказать, когда в сокете доступно больше данных. Затем просто работайте с буфером приложения.

...