Странные редкие неупорядоченные данные, полученные с помощью Indy
-
19-09-2019 - |
Вопрос
У нас возникла странная проблема с Indy10: две большие строки (по несколько сотен символов каждая), которые мы отправляем одну за другой с помощью TCP, появляются на другом конце странным образом переплетающимися.Это происходит крайне редко.
Каждая строка представляет собой полное XML-сообщение, оканчивающееся LF, и обычно процесс READ считывает все XML-сообщение и возвращается, когда видит LF.
Вызов для фактической отправки сообщения защищен критическим разделом вокруг вызова метода writeln IOHandler, поэтому два потока не могут отправлять сообщения одновременно.(Мы уверены, что критический раздел реализован/работает правильно).Эта проблема случается очень редко.Симптомы странные... когда мы отправляем строку A, а затем строку B, на другом конце мы получаем (в тех редких случаях, когда происходит сбой) конечную часть строки A (то есть, в конце есть LF), за которым следует начальная часть строки A, а затем вся строка B, за которой следует один LF.Мы проверили, что свойство «время ожидания» неверно после частичного чтения — мы регистрируем это свойство после каждого чтения, возвращающего содержимое.Кроме того, мы знаем, что в строке нет встроенных символов LF, поскольку мы явно заменяем все небуквенно-цифровые символы в строке пробелами перед добавлением LF и его отправкой.
У нас есть механизмы журналирования внутри критических секций как на передающей, так и на принимающей стороне, поэтому мы можем видеть такое поведение на «проводе».
Мы совершенно сбиты с толку и задаемся вопросом (хотя это всегда самая низкая вероятность), могут ли быть какие-то низкоуровневые проблемы Indy, которые могут вызвать эту проблему? например, буферы отправляются в неправильном порядке... очень трудно поверить, что это может быть проблемой, но мы хватаемся за соломинку.
Есть ли у кого-нибудь блестящие идеи?
Решение
Есть ли у вас несколько потоков, одновременно читающих из одного и того же сокета на принимающей стороне?Даже простой запрос статуса Connected() приводит к чтению.Если вы не будете осторожны, это может привести к тому, что ваши несколько потоков будут читать входящие данные и сохранять их в IOHandler.InputBuffer в случайном порядке.
Другие советы
Вы могли бы попробовать Вайршарк чтобы узнать, как передаются данные.Таким образом вы сможете узнать, проблема в сервере или в клиенте.Также не забудьте использовать TCP для получения «гарантированных» достоверных данных в правильном порядке.
Вы используете TCP или UDP?Если вы используете UDP, возможно (и ожидается), что пакеты UDP могут быть получены в другом порядке, чем они были переданы, из-за маршрутизации по сети.В этом случае вам нужно будет добавить какой-то идентификатор пакета к каждому пакету UDP, чтобы получатель мог правильно упорядочить пакеты.
Вы проверили Нэгл настройки IOHandler?У нас была аналогичная проблема, которую мы исправили, установив для UseNagle значение false.В нашем случае пакетная отправка и получение больших объемов данных происходила медленно из-за объединения Нэгла, поэтому это не совсем то же самое, что ваша ситуация.