Данные не передаются между QTcpSockets и Java Sockets

Итак, у меня есть два приложения, одно написано на C++ с использованием Qt5, а другое — на Java. Приложение C++ действует как клиент, который подключается к объекту ServerSocket в приложении Java, которое затем создает экземпляр сокета из соединения. Когда я затем пытаюсь отправить строку на сервер, мне либо приходится отправлять строку повторно (например, 20000 раз), либо сервер вообще ничего не получает.

QString s = " This is a test string that will be sent to the server upon connection\n";
QTcpSocket *sock = new QTcpSocket;
sock->connectToHost(QHostAddress::LocalHost, 5000, QIODevice::ReadWrite);
sock->waitForConnected(5000);
QTextStream out(sock);
while(!sock->waitForBytesWritten(3000)) {
        out << s << endl;
}

Там, где приведенный выше код не дал бы никаких результатов, следующий код дает сегментированные строки, а также дублирующие полученные строки для сервера:

QString s = " This is a test string that will be sent to the server upon connection\n";
QTcpSocket *sock = new QTcpSocket;
sock->connectToHost(QHostAddress::LocalHost, 5000, QIODevice::ReadWrite);
sock->waitForConnected(5000);
QTextStream out(sock);
do {
        out << s << endl;
} while(!sock->waitForBytesWritten(3000) | 1);

Сервер представляет собой простую Java-программу, подобную этой:

ServerSocket ss = new ServerSocket(5000);
Socket s = ss.accept();
DataInputStream in = new DataInputStream(s.getInputStream());
while (true){
        String tmp = in.readUTF();
        System.out.println(tmp);
        if (tmp.contains(" ")){
              break;
}

Я ожидаю, что вывод будет простым This is a test string that will be sent to the server upon connection; однако результат либо ничего, либо что-то вроде этого:

his is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

 This is a test string that will be sent to the server upon connection

Есть ли у вас какие-либо идеи относительно того, как я могу решить эту проблему?

Я не знаю «Q», но если бы я писал клиент на Java, мне пришлось бы отправить «flush» после вызова out, чтобы он действительно отправил пакет.

markspace 23.03.2019 18:34

Промывка ничего не изменила

Ohunter 23.03.2019 18:40

При сбросе сообщение будет перемещено из буфера потока в сетевой стек, но TCP не дает никаких гарантий, что сетевой стек не будет буферизовать его или разделять на несколько пакетов TCP. Если вы хотите отправлять отдельные сообщения в потоке TCP, вам необходимо заключить сообщения в протокол.

user4581301 23.03.2019 18:42

У вас есть идея, как бы я сделал это в Qt?

Ohunter 23.03.2019 18:47

Если очистка не имеет значения, то я думаю, что ваш стек протоколов сломан. Лучше спросите у QT, как у них работает. Хотя «сброс» не гарантируется, стек протоколов должен приложить все усилия для отправки данных по сети, и на самом деле это всегда должно быть успешным.

markspace 23.03.2019 18:48
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
5
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Таким образом, решение состояло в том, чтобы прочитать данные в byte[], а затем преобразовать с помощью конструктора строки в строку как таковую:

ServerSocket ss = new ServerSocket(5000);

Socket s = ss.accept();

DataInputStream in = new DataInputStream(s.getInputStream());

byte[] b = new byte[1024];
in.read(b);

String tmp = new String(b, "UTF8");
System.out.println(b);
System.out.println(tmp);

Я понятия не имею, почему, но это решение, к которому я пришел. Клиент практически остался прежним, хотя были внесены небольшие изменения:

QString s = "This is a test string that will be sent to the server upon connection\n";

QTcpSocket *sock = new QTcpSocket;

sock->connectToHost(QHostAddress::LocalHost, 5000, QIODevice::ReadWrite);

sock->waitForConnected(5000);


do {
        sock->write(s.toUtf8());
        sock->flush();

        sock->waitForBytesWritten();
} while (sock->isValid() && sock->bytesToWrite() > 0);

См. мою заметку (5), чтобы понять, почему ваше решение работает.

Jens 23.03.2019 23:39

(1) waitForBytesWritten может не работать в Windows - лучше используйте сигнал bytesWritten()

(2) Петля

while(!sock->waitForBytesWritten(3000) | 1);

выглядит как бесконечный цикл, не зависящий от кода возврата от waitForBytesWritten

(3) Какова идея waitForBytesWritten в контексте вашей программы? Он может вернуться после первого байта, записанного в поток!

(4) В чем идея

if (tmp.contains(" ")){
              break;

Для меня это выглядит так, как будто он может сломаться после получения любого пробела - например. первый пробел после «Это». Он также может сломаться после нескольких строк, в зависимости от того, сколько выдает readUTF (я не эксперт в Java).

(5) readUTF ожидает строки в модифицированном формате UTF8, но Qt не будет отправлять строки в модифицированном формате UTF8 (с начальным 16-битным целым числом, содержащим длину). Таким образом, Java будет интерпретировать первые два символа ('Th') как длину, а затем может начаться лотерея - в зависимости от этих двух символов декодирование будет возвращать, казалось бы, произвольные результаты.

Итак, вы говорите, что если бы я добавил длину строки к массиву байтов, содержащему длину, которая решила бы это, как вы думаете?

Ohunter 23.03.2019 23:40

В зависимости от ваших строк readUTF может выдавать неожиданные результаты, например. кодирование nul и дополнительных символов в Qt отличается.

Jens 23.03.2019 23:44

Но разве набор символов UTF не является стандартным, поэтому при использовании метода QString toUtf8() этого следует избегать?

Ohunter 23.03.2019 23:46

UTF стандартизирован, но readUTF читает не стандартизированный UTF8, а вместо этого «модифицированный UTF8». Просто погуглите термин или прочитайте описание интерфейса Java здесь!

Jens 25.03.2019 09:42

Другие вопросы по теме