Итак, у меня есть два приложения, одно написано на 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
Есть ли у вас какие-либо идеи относительно того, как я могу решить эту проблему?
Промывка ничего не изменила
При сбросе сообщение будет перемещено из буфера потока в сетевой стек, но TCP не дает никаких гарантий, что сетевой стек не будет буферизовать его или разделять на несколько пакетов TCP. Если вы хотите отправлять отдельные сообщения в потоке TCP, вам необходимо заключить сообщения в протокол.
У вас есть идея, как бы я сделал это в Qt?
Если очистка не имеет значения, то я думаю, что ваш стек протоколов сломан. Лучше спросите у QT, как у них работает. Хотя «сброс» не гарантируется, стек протоколов должен приложить все усилия для отправки данных по сети, и на самом деле это всегда должно быть успешным.




Таким образом, решение состояло в том, чтобы прочитать данные в 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), чтобы понять, почему ваше решение работает.
(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') как длину, а затем может начаться лотерея - в зависимости от этих двух символов декодирование будет возвращать, казалось бы, произвольные результаты.
Итак, вы говорите, что если бы я добавил длину строки к массиву байтов, содержащему длину, которая решила бы это, как вы думаете?
В зависимости от ваших строк readUTF может выдавать неожиданные результаты, например. кодирование nul и дополнительных символов в Qt отличается.
Но разве набор символов UTF не является стандартным, поэтому при использовании метода QString toUtf8() этого следует избегать?
UTF стандартизирован, но readUTF читает не стандартизированный UTF8, а вместо этого «модифицированный UTF8». Просто погуглите термин или прочитайте описание интерфейса Java здесь!
Я не знаю «Q», но если бы я писал клиент на Java, мне пришлось бы отправить «flush» после вызова
out, чтобы он действительно отправил пакет.