Indy TCPClient и мошеннический байт в InputBuffer - PullRequest
5 голосов
/ 07 марта 2012

Я использую следующие несколько строк кода для записи и чтения с внешнего модема / маршрутизатора (или устройства) по IP.

TCPClient.IOHandler.Write(MsgStr);
TCPClient.IOHandler.InputBuffer.Clear; 
TCPClient.IOHandler.ReadBytes(Buffer, 10, True);

MsgStr - это строковый тип, содержащий текст, который яотправка на мое устройство.Буфер объявлен как TIdBytes.Я могу подтвердить, что IOHandler.InputBufferIsEmpty возвращает True непосредственно перед вызовом ReadBytes.

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

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

например, 10 байтов, которые я ожидаю, могут быть: # 6A1EF1090 # 3 , но я получаю . # 6A1EF1090 .в этом примере у меня полная остановка, где ее не должно быть.

Если я попытаюсь отправить еще раз, все будет работать нормально.(т.е. 2-я запись отправлена ​​после установления соединения).Что странно (для меня), использование Socket Sniffer не показывает возвращаемый случайный байт.Если я создаю свой собственный «сервер», чтобы получить ответ и отправить что-то обратно, он работает нормально в 100% случаев.Другое программное обеспечение - т.е. не мое программное обеспечение - нормально взаимодействует с устройством (но, конечно, я понятия не имею, как они анализируют данные).

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

Спасибо

РЕДАКТИРОВАТЬ

Я использую Delphi 7 и Indy 10.5.8

ОБНОВЛЕНИЕ

Хорошо.После долгих испытаний и поисков я не приблизился к поиску этого решения.Я получаю два основных сценария.1 - первый байт отсутствует и 2 - «введен» байт в начале принятого пакета.При использовании TIdLogEvent и TIdLogDebug оба показывают либо отсутствующий байт, либо начальный введенный байт в зависимости от ситуации.Так что мое утверждение ReadBytes, приведенное выше, последовательно показывает, что, по моему мнению, существует в Indy.

Кроме того, для дальнейшей проверки я загрузил и установил компоненты ICS.К сожалению (или к счастью, в зависимости от того, как вы на это смотрите), это не показывало те же проблемы, что и в Indy.Это не показывало пропущенный первый байт и не показывало введенный байт в начале.Тем не менее, я только провел поверхностное тестирование, но Indy производит поведение «почти сразу», тогда как ICS еще не производил его вообще.

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

Ответы [ 2 ]

3 голосов
/ 07 марта 2012

Последний параметр (True)

TCPClient.IOHandler.ReadBytes(Buffer, 10, True);

вызывает чтение до и добавляет вместо замены содержимого буфера.

Это требует, чтобы размер и содержимое буфера были установлены правильно в первую очередь.

Если параметр имеет значение False, содержимое буфера будет заменено на указанное количество байтов.

1 голос
/ 07 марта 2012

ReadBytes() не внедряет неконтролируемые байты в буфер, поэтому есть только две возможности, о которых я могу подумать, учитывая предоставленную вами ограниченную информацию:

  1. Устройство действительно отправляет дополнительный байт при первоначальном подключении, как предложено mj2008. Если анализатор пакетов не обнаруживает его, попробуйте подключить к вашему TIdTCPClient один из собственных компонентов Indy TIdLog..., например TIdLogFile или TIdLogEvent, чтобы проверить, что TIdTCPClient фактически получает из сокета.

  2. у вас есть другой поток, считывающий то же самое соединение в то же самое время, повреждающий InputBuffer. Даже вызов TIdTCPClient.Connected() выполнит чтение. Не выполняйте чтение в нескольких потоках одновременно, если вы используете потоки.

...