![]() |
Модераторы: Snowy, Poseidon, MetalFan |
![]() ![]() ![]() |
|
DelphiTester |
|
|||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 3.5.2007 Репутация: нет Всего: нет |
В итоге вылетают ошибки "Access Violation". Причем если не циклом, а слать только одному клиенту, то всё отлично доходит. Здесь видимо либо курсор перемещается, но куда? (я же его восстанавливаю на нулевую позицию). Либо MS вообще опустошается.. такое возможно? Как эту проблему можно решить?? Добавлено через 4 минуты и 57 секунд Приношу извинения за столь кривое оформление заголовка темы, ошибся полем не туда вписал ![]() Попробую здесь заголовок изложить: суть в том, что есть TServerSocket и подключенные клиенты, нужно разослать по ним TMemoryStream (в ней картинка). Если рассылать на один - то отлично. На много - ошибки. Есть ли идеи как их исправить? |
|||
|
||||
Snowy |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 11363 Регистрация: 13.10.2004 Где: Питер Репутация: 53 Всего: 484 |
Переведи сервер в ThreadBlocking режим.
По дефолту он NonBlocking, что может вызывать коллизии. |
|||
|
||||
DelphiTester |
|
|||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 3.5.2007 Репутация: нет Всего: нет |
Не прокатывает..
Я передаю через TCP протокол. Алгоритм у меня такой, что клиенты получают порциями большую картинку (3 мб). Причём в вышеприведённом цикле передаётся именно порция, не полная картинка. Ну в прочем, наверное, какая разница часть там или полная?! т.е. в том цикле раздача очередной части от картинки. (клиенты знают, что картинка ещё не завершилась и "ждут" её окончания). Блее подробно опишу поведение клиентов, может это как-то поможет понять Вам в чём проблема здесь.. при ThreadBlocking сервера: 1. Запущен Сервер и один Клиент - передача отличная 2. Запущен Сервер и два Клиента - один получает, у другого Access Violation Это сообщение отредактировал(а) DelphiTester - 22.5.2007, 00:57 |
|||
|
||||
Snowy |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 11363 Регистрация: 13.10.2004 Где: Питер Репутация: 53 Всего: 484 |
Разница очень существенная.
Сервер - существо мультитредовое. А мемористрим расчитан только на сингловое обращение. Вывод - либо сделать множество мемористримов, либо сделать фикчированный буфер в памяти, у которого нет указателя на текущую позицию. В любом случае, при работе с множеством коннектов, стоит иметь ввиду, что пользование данными далеко не эксклюзивное, и следует изолировать переменные данные разных коннектов. В данном случае, слабое звено - свойство Position. Чтобы его изолировать - нужно использовать отдельный стрим для каждого коннекта, либо использовать единый буфер, не имеющий переменного указателя. Например массив или string. |
|||
|
||||
DelphiTester |
|
|||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 3.5.2007 Репутация: нет Всего: нет |
String для картинки?? А разве там могут храниться без повреждения Binary-данные?
Добавлено через 1 минуту и 56 секунд Интересно, а если я UDP протокол здесь буду использовать, то это сможет решить проблему? прямо на этапе её возникновения ![]() Добавлено через 2 минуты и 59 секунд если не ошибаюсь, в UDP ведь можно отправить одним большим блоком данных.. Вот только пролезет ли блок в 3-4 мб? ![]() Добавлено через 5 минут и 11 секунд
Честно говоря, не понимаю всё-таки, почему именно здесь ошибка.. Я же указатель откатываю на 0 и рассылаю с этого места поток, затем заново на 0... Мне кажется всё должно прокатывать.. ![]() |
|||
|
||||
DelphiTester |
|
|||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 3.5.2007 Репутация: нет Всего: нет |
Блин.. всё-таки алгоритм проги чуть иной. В цикле кидается ПОЛНЫЙ пакет, а дальше уже средствами сокета он бьётся (походу частями по 8кб). Итого цикл выполняется при двух клиентах - два раза, посылая каждому по полному пакету данных.
Ну а далее уже сокет дробит эти пакеты. (собираются они нормально, т.к. пакеты с "контрольными суммами" размера пакета). Тока вот видимо не всё уходит с сервера.. Всмысле не всем. Да и использовать UDP тоже не выход. На него часто навешивают жёсткие правила на файерволле... Безвыходное просто положение :( Добавлено через 8 минут и 46 секунд
И как такой "набор символов" или переменную послать клиенту? Не через SendStream же полагаю..? Я попытался создать ещё один TMemoryStream откопировать тот который хотел послать и заслать и тот и другой, причём не в цикле, а в "ручную". Ошибок нет, но до второго клиента видимо доходит пустой стрим.. |
|||
|
||||
Snowy |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 11363 Регистрация: 13.10.2004 Где: Питер Репутация: 53 Всего: 484 |
Вот выводить эти данные на экран - это может быть проблемой. А хранить в нём можно что угодно.
Идёт одновременное обращение. И код нужно строить с учётом того, что другой коннект всегда может вмешаться до завершения процесса. Сам можешь представить, что будет, когда другой коннект сбросит Position на ноль в процессе передачи данных другим коннектом. Сервер - это Вам не кусок мыла съесть. Здесь нужно делать поправку на многопользовательский режим. |
||||||
|
|||||||
DelphiTester |
|
||||||||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 3.5.2007 Репутация: нет Всего: нет |
В общем смотрите чего я достиг в этом деле.
MS_Res - стрим который нужно разослать MS_Res_Bak - пытаюсь сохранять этот же стрим Этот код работает с двумя клиентами (как в НонБлокинг, так и в ТредБлокинг режимах):
Пытаюсь написать тот же код, но с циклом. И уже не получается:
У сервера возникает AccessViolation. Ясно, что в отправке ошибка. И где же тут возникает неверное обращение к памяти?? вроде всё просчитал.. нет? Добавлено через 5 минут и 28 секунд
Мда, видимо в своём вышеидущем посте я сделал именно такую ошибку... Т.е. мне теперь, что нужно этот стрим перегнать в String тип? Если так, то как отправлять его? Через SendText? ![]() Или опять через SendStream? Но если так. то непонятен смысл перегона в String, если после надо будет заново в Стрим кидать.. блин видимо я совсем запутался ![]() Добавлено через 12 минут и 33 секунды
А.. вот терь до меня дошло в чём юмор тут.. Только остаётся за гранью понимания как я "эту переменную", которая будет без указателя пошлю клиентам... через какой метод?? Добавлено через 14 минут и 51 секунду Хм.. если ты говоришь, что String хранить может и бинарные данные, то может и правда перекачать Стрим в Стринг и этот Стринг отправить через SendText? Или бред? |
||||||||
|
|||||||||
DelphiTester |
|
|||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 3.5.2007 Репутация: нет Всего: нет |
Забегая вперёд.. а как перевести Стрим в Стринг, если это будет приемлемым решением?
Нужно ведь посимвольно, насколько я понимаю? Как достать из стрима символ, чтобы он был совместим со сторокой и добавить его успешно в эту строку? |
|||
|
||||
drkot |
|
|||
![]() Ищущий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1042 Регистрация: 5.5.2006 Репутация: 0 Всего: 8 |
Зачастую проходят пакеты не более 1024байт, все остальное перяется, зависит от настроек операционки и маршрутизаторов.
![]() Плакаль. Собственный поток для каждого клиента или единый буфер. Это сообщение отредактировал(а) drkot - 22.5.2007, 10:02 -------------------- Ошибка не становится истиной по причине широкого распространения, как и Истина не становится Ошибкой из-за того, что никто её не видит. |
|||
|
||||
DelphiTester |
|
|||
Новичок Профиль Группа: Участник Сообщений: 24 Регистрация: 3.5.2007 Репутация: нет Всего: нет |
drkot
![]() >> Собственный поток для каждого клиента Не понял о каком именно потоке речь идёт? >> или единый буфер. Здесь как раз подойдёт переменная String типа?? Если так, то как переслать такую переменную (там бинарные данные) и как собсно перекачать из TMemoryStream в String? |
|||
|
||||
Snowy |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 11363 Регистрация: 13.10.2004 Где: Питер Репутация: 53 Всего: 484 |
|
|||
|
||||
drkot |
|
|||
![]() Ищущий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1042 Регистрация: 5.5.2006 Репутация: 0 Всего: 8 |
в данном случае TMemoryStream. создаеш, загружаеш данные, после отправки поток разрушаеш. Но можно и многопоточность организовать (TThread). да (как простейший вариант). тк. строки в паскале это весьма хитрый зверь; можно сказать динамический буфер на обрабатываемый на уровне языка (насколько знаю в си такого нет). ms.read(s[1], count); Добавлено через 1 минуту и 30 секунд ммммда. долго я думал ![]() -------------------- Ошибка не становится истиной по причине широкого распространения, как и Истина не становится Ошибкой из-за того, что никто её не видит. |
|||
|
||||
greenpc |
|
|||
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 29.1.2007 Репутация: нет Всего: нет |
где-то читал что после отправки поток уничтожается
Хотя могу ошибаться |
|||
|
||||
Snowy |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 11363 Регистрация: 13.10.2004 Где: Питер Репутация: 53 Всего: 484 |
Давайте определимся с терминологией.
стримы - это стримы, а треды - это треды. А то "потоками" только запутываем, превращая текст в непонятно что. Добавлено через 2 минуты и 26 секунд Вобщем основная мысль какая: стрим не подходит для единого хранилища данных, т.к. он модифицируется в процессе чтения. Поэтому нужно использовать другое - немодифицированное хранилище. Это любой блок данных. Для простоты удобно использовать стринг. Перед отправкой забить в него содержимое стрима и рассылать уже это стринг. |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Delphi: Сети" | |
|
Запрещено: 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делится вскрытыми компонентами
Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Snowy, Poseidon, MetalFan. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Delphi: Сети | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |