![]() |
Модераторы: Snowy, Poseidon, MetalFan |
![]() ![]() ![]() |
|
StealeR |
|
||||||
Новичок Профиль Группа: Участник Сообщений: 37 Регистрация: 14.11.2005 Репутация: нет Всего: нет |
Всем привет. Прошу помощи...Проблема следующая. Есть серверная часть, которая собирает некоторую инфу в динамический массив, который потом обрабатывается. С этим все в норме.
Есть клиентская часть (ClientSocket1: TClientSocket;), которая отлично подключается и периодически отсылает таймером на сервер строку-команду, указывающую серверу, что ему отправить в ответ:
Сервер (ServerSocket1: TServerSocket;), при приеме этой команды делает следующее:
т.е. при получении команды "отдать всю инфу" запускаем цикл по массиву, на каждой итерации заполняем переменную новыми данными и отсылаем. Элементов в массиве (и соответственно, итераций) немного, от нуля до 30-40 максимум, зависит от конфигурации сервера, и в течении сеанса связи неизменно. Опрос происходит примерно раз в секунду. Затык происходит на клиенте. При событии получения OnRead смотрю сколько байт получено и вижу, что размер полученных данных варьируется и всегда кратен размеру одной записи. Честно говоря, расчитывал, что будет проще - отправил одну запись и получил тоже одну, а не пачку из 1-20 штук. Код на приёмке следующий:
Из-за того, что принимаемые данные содержат заранее неизвестное N-ое кол-во записей, а принимаем только одну (первую), то и имеем на выходе наполовину заполненный массив (который отдельным потоком отрисовывает на форме эту инфу). Кто с подобными вещами уже сталкивался, подскажите, как быть. Может быть есть какой обходной путь? Или наведите на мысль верную, буду премного благодарен, а то поскольку по профессии не являюсь программистом, то собственного тяму не хватает разобраться в ситуёвине за отсутствием опыта... Это сообщение отредактировал(а) StealeR - 25.9.2014, 17:30 |
||||||
|
|||||||
kami |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
отправлять строку (скорее всего - переменной длины) в TCP-соединение - это чревато.
Правильно, так и должно быть Неправильно, это частный случай. На самом деле - может и не быть кратен. Кратность получилась скорее всего из-за работы в пределах одного компьютера, либо в ненагруженной локалке. В очередной раз протолкну свои велосипеды ![]() При их использовании - что отправишь, то и получишь. Безо всяких кратностей, всегда 1:1 Это сообщение отредактировал(а) kami - 25.9.2014, 22:20 Присоединённый файл ( Кол-во скачиваний: 16 ) ![]() |
|||
|
||||
StealeR |
|
|||
Новичок Профиль Группа: Участник Сообщений: 37 Регистрация: 14.11.2005 Репутация: нет Всего: нет |
Алексей, благодарю за предложенную альтернативу, буду пробовать
![]() По поводу кратности: да, действительно, все это тестировалось в не сильно нагруженной сети и по результатам логирования длины принимаемых данных (несколько сотен отправок/приемов) результат в 100% случаев оказывался кратен |
|||
|
||||
drkot |
|
|||
![]() Ищущий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1042 Регистрация: 5.5.2006 Репутация: 0 Всего: 8 |
что мешает передавать количество? Также ничего не мешает запрашивать записи по номерам, то 0 и выше... когда доходим до конца списка сервер возвращает признак ошибки Добавлено через 2 минуты и 43 секунды как вариант протокола: 1) количество записей 2) длинна записи 3) тело записи 4) к пункту 2 -------------------- Ошибка не становится истиной по причине широкого распространения, как и Истина не становится Ошибкой из-за того, что никто её не видит. |
|||
|
||||
StealeR |
|
|||
Новичок Профиль Группа: Участник Сообщений: 37 Регистрация: 14.11.2005 Репутация: нет Всего: нет |
дело в том, что общее кол-во передаваемых записей мне было как раз известно. В единице экземпляра записи передаются значения "всего" и "текущая запись", неизвестно было кол-во записей в одной конкретной пересылке. пока сидел без инета, решил проблему другим путем - из необходимого набора записей на сервере формирую ответ в формате JSON и пересылаю его через Socket.SendText. На клиенте делаю ReceiveText и разбираю JSON обратно в массив записей. Работает на ура. Алексей, еще раз спасибо за Ваш "велосипед", на досуге по-разбираюсь. Надеюсь, еще пригодится ![]() Это сообщение отредактировал(а) StealeR - 27.9.2014, 16:37 |
|||
|
||||
kami |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
Это хорошо, только опять не учитываете 3 момента: 1. SendText - функция. Она возвращает, сколько байт реально отправлено. Отсюда вывод - может быть отправлен не весь текст, а только его часть. Оставшееся надо "досылать", когда буфер сокета освободится (и опять - возможно, отправится не весь остаток). 2. SendText (по крайней мере до Delphi2010) использует AnsiString, а не UnicodeString. Могут возникнуть проблемы с не-английскими символами. 3. Используя JSON Вы увеличили объем передаваемых данных. Соответственно - увеличилась вероятность того, что на приемный конец в событие OnRead придет только часть данных, а оставшиеся - в другом (или даже других) OnRead. К сожалению, при тестировании такие проблемы обычно не всплывают. А в условиях боевой эксплуатации отловить подобное будет сложно, и ошибки скорее всего будете искать в другом месте. Чтобы убедиться, что всё работает правильно, проще всего в цикле отправить пару тысяч записей. Этим вы, возможно, добъетесь того, что заполнится буфер на передачу и воспроизведете момент №1, а приемный буфер склеит между собой несколько отправок (вполне возможно - разрезав где-нибудь посредине. Как пример - отправляете "123" и "456", а приходит "1234" и "56") - момент №3. Добавлено через 1 минуту и 31 секунду Еще раз повторюсь - при тестировании всё будет идеально, единичные сбои не в счет - их не воспроизвести. А при переходе на боевой режим работы вы подобное не отловите и не сможете понять, в чем проблема. |
|||
|
||||
drkot |
|
|||
![]() Ищущий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1042 Регистрация: 5.5.2006 Репутация: 0 Всего: 8 |
если делать в пределах локалхост, то проблемы пересылки никогда не проявятся, ее попросту нет. а чтобы не проблем было меньше лучше пользоваться готовыми надстройками типа indy или альтернатив. -------------------- Ошибка не становится истиной по причине широкого распространения, как и Истина не становится Ошибкой из-за того, что никто её не видит. |
|||
|
||||
kami |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 6 Всего: 72 |
Это опять-таки частный случай, выполняемый в силу особенностей реализации внутренностей Windows. Полагаться на эту недокументированную возможность не стоит. И - такое поведение избавляет от разбиения пакетов, но никак не от их склейки. |
|||
|
||||
StealeR |
|
|||
Новичок Профиль Группа: Участник Сообщений: 37 Регистрация: 14.11.2005 Репутация: нет Всего: нет |
kami, я с Вами полностью согласен относительно вероятности недополучения информации, и возможно, придется с этим столкнуться. Временно (поскольку поджимают сроки) обошел вероятность возникновения этой проблемы обработкой полученной информации на клиенте путем проверки корректности JSON-строки. Если движок считает строку корректной - принимаем и парсим согласно алгоритму. На текущий момент с рабочей среде (~100 станций в сети, между сервером и клиентом 2 свитча - 1 дорогой в серверной, 1 дешевый в кабинете) сервер и клиент работают стабильно.
Это сообщение отредактировал(а) StealeR - 29.9.2014, 10:47 |
|||
|
||||
StealeR |
|
|||
Новичок Профиль Группа: Участник Сообщений: 37 Регистрация: 14.11.2005 Репутация: нет Всего: нет |
kami, все-таки дошли руки-ноги до необходимости использовать Ваши наработки. Небольшой косячок в архиве обнаружился - не приложен файл uCommonFunctions.pas, который в процессе отладки был заменен на Math
![]() |
|||
|
||||
StealeR |
|
|||
Новичок Профиль Группа: Участник Сообщений: 37 Регистрация: 14.11.2005 Репутация: нет Всего: нет |
kami, благодарю за предоставленный "велосипед", едет на ура
![]() |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Delphi: Сети" | |
|
Запрещено: 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делится вскрытыми компонентами
Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Snowy, Poseidon, MetalFan. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Delphi: Сети | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |