QT QTcpServer telnet, принимающий символы \ r \ n - PullRequest
3 голосов
/ 04 апреля 2011

Я пишу QTcpServer. Я использовал telnet.exe в качестве клиента для тестирования. При новом клиентском соединении мой сервер отправляет клиенту сообщение Hi!, которое покажется - пока все в порядке.

Но когда я что-то печатаю в окне telnet.exe, readyRead() испускается для каждого символа . Я хочу, чтобы он был отправлен только после \r\n! В чем проблема? Это природа telnet.exe в Windows? Потому что я использовал telnet на своем Linux-компьютере, и он отправляет строку только после \r\n, как и ожидалось.

Ответы [ 3 ]

3 голосов
/ 06 октября 2011

Вместо ввода сообщения нажмите CTRL + ] , а затем введите send YOURMESSAGE\r\n

3 голосов
/ 04 апреля 2011

К сожалению, именно так работает клиент Windows telnet.exe, и изменить его невозможно.

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

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

1 голос
/ 04 апреля 2011

Да, между Windows и Linux с CR LF есть некоторые различия, это "нормально".

Один из подходящих подходов - использовать буфер, а затем ждать готовности данных или тайм-аута.,Например, ваш токен-разделитель может быть «\ r», и если после его удаления вы получите «\ n».

Вот пример, ожидающий токен от пользовательского протокола :

int Connection::readDataIntoBuffer(int maxSize)
 {
     if (maxSize > MaxBufferSize)
         return 0;

     int numBytesBeforeRead = buffer.size();
     if (numBytesBeforeRead == MaxBufferSize) {
         abort();
         return 0;
     }

     while (bytesAvailable() > 0 && buffer.size() < maxSize) {
         buffer.append(read(1));
         if (buffer.endsWith(SeparatorToken))
             break;
     }
     return buffer.size() - numBytesBeforeRead;
 }

См. http://doc.qt.nokia.com/stable/network-network-chat-connection-cpp.html

В зависимости от того, что вам нужно, другое предложение - попробовать придерживаться какого-то стандартного протокола .Таким образом, вы можете тестировать с различными типами клиентов.

Если вы хотите придерживаться своего собственного протокола, я предлагаю вам написать свой собственный клиент и написать надлежащие тестовые случаи для совместной работы с вашим сервером.Qt делает это легко и быстро;) Посмотрите на примеры сети.

Edit:

Вы можете рассмотреть readline() вместо read() на вашем QTcpSocket, что является QIODevice.Он ожидает новой строки вместо read () (см. Выдержку из документа ниже).Однако это дает меньше контроля над окончанием вашей строки:

qint64 QIODevice::readLine ( char * data, qint64 maxSize )

Из документа:

Данные считываются до тех пор, пока не будет выполнено любое из следующих условий:

  • Первый символ '\ n' читается.
  • maxSize - считывается 1 байт.
  • Обнаружен конец данных устройства.

Секретным компонентом в Qt является асинхронныйуправляемый сигналом дизайн .См. Раздел «Сеть / конечные автоматы» в статье Потоки, события и объекты QObjects для некоторых идей.

...