Модераторы: Snowy, Poseidon, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Нужно разослать картинку по всем подключенным клиП 
V
    Опции темы
DelphiTester
Дата 21.5.2007, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 3.5.2007

Репутация: нет
Всего: нет



Код

MS : TMemoryStream;

//.. создание и наполнение MS...

// рассылка:
for I := 0 to ServerSocket1.Socket.ActiveConnections-1 do begin
  MS.Position := 0;
  ServerSocket1.Socket.Connections[I].SendStream( MS );
end;

В итоге вылетают ошибки "Access Violation". Причем если не циклом, а слать только одному клиенту, то всё отлично доходит.

Здесь видимо либо курсор перемещается, но куда? (я же его восстанавливаю на нулевую позицию). Либо MS вообще опустошается.. такое возможно?
Как эту проблему можно решить??

Добавлено через 4 минуты и 57 секунд
Приношу извинения за столь кривое оформление заголовка темы, ошибся полем не туда вписал smile а подправить нет возможности.

Попробую здесь заголовок изложить: суть в том, что есть TServerSocket и подключенные клиенты, нужно разослать по ним TMemoryStream (в ней картинка). Если рассылать на один - то отлично. На много - ошибки. 

Есть ли идеи как их исправить?
PM MAIL   Вверх
Snowy
Дата 22.5.2007, 00:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 53
Всего: 484



Переведи сервер в ThreadBlocking режим.
По дефолту он NonBlocking, что может вызывать коллизии.
PM MAIL   Вверх
DelphiTester
Дата 22.5.2007, 00:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 3.5.2007

Репутация: нет
Всего: нет



Не прокатывает..

Я передаю через TCP протокол. Алгоритм у меня такой, что клиенты получают порциями большую картинку (3 мб).
Причём в вышеприведённом цикле передаётся именно порция, не полная картинка. Ну в прочем, наверное, какая разница часть там или полная?!

т.е. в том цикле раздача очередной части от картинки. (клиенты знают, что картинка ещё не завершилась и "ждут" её окончания).




Блее подробно опишу поведение клиентов, может это как-то поможет понять Вам в чём проблема здесь..

при ThreadBlocking сервера:

1. Запущен Сервер и один Клиент - передача отличная
2. Запущен Сервер и два Клиента - один получает, у другого Access Violation

Это сообщение отредактировал(а) DelphiTester - 22.5.2007, 00:57
PM MAIL   Вверх
Snowy
Дата 22.5.2007, 00:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 53
Всего: 484



Разница очень существенная.
Сервер - существо мультитредовое.
А мемористрим расчитан только на сингловое обращение.
Вывод - либо сделать множество мемористримов, либо сделать фикчированный буфер в памяти, у которого нет указателя на текущую позицию.
В любом случае, при работе с множеством коннектов, стоит иметь ввиду, что пользование данными далеко не эксклюзивное, и следует изолировать переменные данные разных коннектов.
В данном случае, слабое звено - свойство Position.
Чтобы его изолировать - нужно использовать отдельный стрим для каждого коннекта, либо использовать единый буфер, не имеющий переменного указателя.
Например массив или string.
PM MAIL   Вверх
DelphiTester
Дата 22.5.2007, 00:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 3.5.2007

Репутация: нет
Всего: нет



String для картинки?? А разве там могут храниться без повреждения Binary-данные?

Добавлено через 1 минуту и 56 секунд
Интересно, а если я UDP протокол здесь буду использовать, то это сможет решить проблему? прямо на этапе её возникновения smile

Добавлено через 2 минуты и 59 секунд
если не ошибаюсь, в UDP ведь можно отправить одним большим блоком данных.. Вот только пролезет ли блок в 3-4 мб? smile

Добавлено через 5 минут и 11 секунд
Цитата
В данном случае, слабое звено - свойство Position.

Честно говоря, не понимаю всё-таки, почему именно здесь ошибка.. Я же указатель откатываю на 0 и рассылаю с этого места поток, затем заново на 0... Мне кажется всё должно прокатывать.. smile
PM MAIL   Вверх
DelphiTester
Дата 22.5.2007, 01:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 3.5.2007

Репутация: нет
Всего: нет



Блин.. всё-таки алгоритм проги чуть иной. В цикле кидается ПОЛНЫЙ пакет, а дальше уже средствами сокета он бьётся (походу частями по 8кб). Итого цикл выполняется при двух клиентах - два раза, посылая каждому по полному пакету данных.
Ну а далее уже сокет дробит эти пакеты. (собираются они нормально, т.к. пакеты с "контрольными суммами" размера пакета).
Тока вот видимо не всё уходит с сервера.. Всмысле не всем.

Да и использовать UDP тоже не выход. На него часто навешивают жёсткие правила на файерволле... Безвыходное просто положение :(

Добавлено через 8 минут и 46 секунд
Цитата
Чтобы его изолировать - нужно использовать отдельный стрим для каждого коннекта, либо использовать единый буфер, не имеющий переменного указателя.
Например массив или string.

И как такой "набор символов" или переменную послать клиенту? Не через SendStream же полагаю..?

Я попытался создать ещё один TMemoryStream откопировать тот который хотел послать и заслать и тот и другой, причём не в цикле, а в "ручную". Ошибок нет, но до второго клиента видимо доходит пустой стрим..
PM MAIL   Вверх
Snowy
Дата 22.5.2007, 01:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 53
Всего: 484



Цитата(DelphiTester @  22.5.2007,  00:59 Найти цитируемый пост)
String для картинки?? А разве там могут храниться без повреждения Binary-данные?
Там могут храниться любые данные. Это же блок в памяти.
Вот выводить эти данные на экран - это может быть проблемой.
А хранить в нём можно что угодно.

Цитата(DelphiTester @  22.5.2007,  00:59 Найти цитируемый пост)
если не ошибаюсь, в UDP ведь можно отправить одним большим блоком данных.. Вот только пролезет ли блок в 3-4 мб?
Нет конечно. В пакет пролезет менее 64кб - не более.

Цитата(DelphiTester @  22.5.2007,  00:59 Найти цитируемый пост)
Честно говоря, не понимаю всё-таки, почему именно здесь ошибка.. Я же указатель откатываю на 0 и рассылаю с этого места поток, затем заново на 0...
Когда речь идёт о сервере, то нет никакого эксклюзивного пользования ресурсом.
Идёт одновременное обращение.
И код нужно строить с учётом того, что другой коннект всегда может вмешаться до завершения процесса.
Сам можешь представить, что будет, когда другой коннект сбросит Position на ноль в процессе передачи данных другим коннектом.
Сервер - это Вам не кусок мыла съесть.
Здесь нужно делать поправку на многопользовательский режим.
PM MAIL   Вверх
DelphiTester
Дата 22.5.2007, 01:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 3.5.2007

Репутация: нет
Всего: нет



В общем смотрите чего я достиг в этом деле.

MS_Res - стрим который нужно разослать
MS_Res_Bak - пытаюсь сохранять этот же стрим

Этот код работает с двумя клиентами (как в НонБлокинг, так и в ТредБлокинг режимах):
Код
MS_Res_Bak := TMemoryStream.Create;
      MS_Res.Position := 0;
      MS_Res_Bak.CopyFrom ( MS_Res, MS_Res.Size );

      MS_Res.Position := 0;
      Sender_ServerSocket.Socket.Connections[0].SendStream( MS_Res );

      MS_Res_Bak.Position := 0;
      Sender_ServerSocket.Socket.Connections[1].SendStream( MS_Res_Bak );



Пытаюсь написать тот же код, но с циклом. И уже не получается:
Код

    MS_Res_Bak := TMemoryStream.Create;

    for I := 0 to Sender_ServerSocket.Socket.ActiveConnections-1 do begin

      MS_Res.Position := 0;
      MS_Res_Bak.Position := 0;
      MS_Res_Bak.CopyFrom ( MS_Res, MS_Res.Size );

      MS_Res.Position := 0;
      Sender_ServerSocket.Socket.Connections[I].SendStream( MS_Res );

      MS_Res.Position := 0;
      MS_Res_Bak.Position := 0;
      MS_Res.CopyFrom( MS_Res_Bak, MS_Res_Bak.Size );

    end;

У сервера возникает AccessViolation. Ясно, что в отправке ошибка. И где же тут возникает неверное обращение к памяти?? вроде всё просчитал.. нет?

Добавлено через 5 минут и 28 секунд
Цитата
Здесь нужно делать поправку на многопользовательский режим.

Мда, видимо в своём вышеидущем посте я сделал именно такую ошибку...

Т.е. мне теперь, что нужно этот стрим перегнать в String тип? Если так, то как отправлять его? Через SendText? smile
Или опять через SendStream? Но если так. то непонятен смысл перегона в String, если после надо будет заново в Стрим кидать..

блин видимо я совсем запутался smile :(

Добавлено через 12 минут и 33 секунды
Цитата
И код нужно строить с учётом того, что другой коннект всегда может вмешаться до завершения процесса.

А.. вот терь до меня дошло в чём юмор тут.. Только остаётся за гранью понимания как я "эту переменную", которая будет без указателя пошлю клиентам... через какой метод??

Добавлено через 14 минут и 51 секунду
Хм.. если ты говоришь, что String хранить может и бинарные данные, то может и правда перекачать Стрим в Стринг и этот Стринг отправить через SendText? Или бред?
PM MAIL   Вверх
DelphiTester
Дата 22.5.2007, 09:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 3.5.2007

Репутация: нет
Всего: нет



Забегая вперёд.. а как перевести Стрим в Стринг, если это будет приемлемым решением?
Нужно ведь посимвольно, насколько я понимаю? Как достать из стрима символ, чтобы он был совместим со сторокой и добавить его успешно в эту строку?
PM MAIL   Вверх
drkot
Дата 22.5.2007, 09:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ищущий
***


Профиль
Группа: Завсегдатай
Сообщений: 1042
Регистрация: 5.5.2006

Репутация: 0
Всего: 8



Цитата(Snowy @  22.5.2007,  01:41 Найти цитируемый пост)
 В пакет пролезет менее 64кб - не более.

Зачастую проходят пакеты не более 1024байт, все остальное перяется, зависит от настроек операционки и маршрутизаторов.

Цитата(DelphiTester @  22.5.2007,  01:44 Найти цитируемый пост)
Пытаюсь написать тот же код, но с циклом. И уже не получается:

 smile 
Плакаль.
Собственный поток для каждого клиента или единый буфер. 


Это сообщение отредактировал(а) drkot - 22.5.2007, 10:02


--------------------
Ошибка не становится истиной по причине широкого распространения,
как и Истина не становится Ошибкой из-за того, что никто её не видит.
PM   Вверх
DelphiTester
Дата 22.5.2007, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 3.5.2007

Репутация: нет
Всего: нет



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

>> Собственный поток для каждого клиента 
Не понял о каком именно потоке речь идёт?

>> или единый буфер. 
Здесь как раз подойдёт переменная String типа??
Если так, то как переслать такую переменную (там бинарные данные) и как собсно перекачать из TMemoryStream в String?

PM MAIL   Вверх
Snowy
Дата 22.5.2007, 11:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 53
Всего: 484



Код

  SetLength(s, ms.Size);
  ms.Read(s[1], ms.Size);
Всё - стрим считан в стринг ;-)
PM MAIL   Вверх
drkot
Дата 22.5.2007, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ищущий
***


Профиль
Группа: Завсегдатай
Сообщений: 1042
Регистрация: 5.5.2006

Репутация: 0
Всего: 8



Цитата(DelphiTester @  22.5.2007,  10:45 Найти цитируемый пост)
Не понял о каком именно потоке речь идёт?

в данном случае  TMemoryStream. создаеш, загружаеш данные, после отправки поток разрушаеш. Но можно и многопоточность организовать (TThread).

Цитата(DelphiTester @  22.5.2007,  10:45 Найти цитируемый пост)
Здесь как раз подойдёт переменная String типа??

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

Цитата(DelphiTester @  22.5.2007,  10:45 Найти цитируемый пост)
перекачать из TMemoryStream в String?

ms.read(s[1], count);

Добавлено через 1 минуту и 30 секунд
ммммда. долго я думал  smile 


--------------------
Ошибка не становится истиной по причине широкого распространения,
как и Истина не становится Ошибкой из-за того, что никто её не видит.
PM   Вверх
greenpc
Дата 22.5.2007, 11:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 29.1.2007

Репутация: нет
Всего: нет



где-то читал что после отправки поток уничтожается
Хотя могу ошибаться
PM   Вверх
Snowy
Дата 22.5.2007, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 53
Всего: 484



Давайте определимся с терминологией.
стримы - это стримы, а треды - это треды.
А то "потоками" только запутываем, превращая текст в непонятно что.

Добавлено через 2 минуты и 26 секунд
Вобщем основная мысль какая: стрим не подходит для единого хранилища данных, т.к. он модифицируется в процессе чтения.
Поэтому нужно использовать другое - немодифицированное хранилище.
Это любой блок данных. Для простоты удобно использовать стринг.
Перед отправкой забить в него содержимое стрима и рассылать уже это стринг.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Сети"
Snowy
Poseidon
MetalFan

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Snowy, Poseidon, MetalFan.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0915 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.