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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Блокирующий режим TServerSocket, коварные потоки... 
:(
    Опции темы
artymen
Дата 23.8.2007, 20:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодер



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

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



Среди множества статей по работе с TSocketServer/Client я нашел только одну небольшую статью по работе в блокирующем режиме. К сожалению она отразила лишь небольшой эпизод из жизни готовой программы-"шаблона". Справочная система делфи тоже не дает ответов. Поэтому вопросов у меня много, ибо моя программа все еще рабоатет неидеально, но по мере продвижения она все реже и реже выдает "Access Violation". Скажу сразу, что многопоточность я изучил достаточно досканально и уже настардался с нею, если мне не поможет кто-то извне, я кончу психушкой.
1. Правильно ли я понимаю "thread-safe code": потокобезопасный код, эта необходимость обусловлена выполнением кода не в VCL-потоке ?
2. В справке написано что в OnClientDisconnect нужно использовать как раз потокобезопасный код. Про другие события этого не сказано. У меня возникают соменния что все остальные события выполняются к контексте VCL-потока.
3. Поведение TServerClientThread очень сильно отличается от обычного TThread. Попытка работать с ним как с TThread приводит к катастрофическим последствиям. Попытки инициализировать поток в OnThreadStart, созданный мною в OnGetThread, приводят к краху, я пробовал это дело контролирвать различными комбинациями приостановки/возобновления потока, результат тот же. Поток завершится (сработает OnThreadEnd) только если я принудительно завершу его в OnClientDisconnect, получив его там из GetClientThread. WaitFor не возварщает управление никогда, даже если он вызван сразу же после Terminate. Вобщем полная неразбериха.
4. Отладка вообще дело мистическое. Когда я трейсю, все рабоатет иделально, как будто дебагер все "смягчает" (например можно спокойно в потоке напрямую обращаться к форме). Таким образом я даже не могу отследить в каком месте кода проиходит сбой ! Могу лишь докадыватсья в каком районе.
5. TEvent (сигнализируемый объект). Он "потокобезопасен" ? Т.е. обязательно ли при обращении к нему (разумеется кроме ожидания сигнала при помощи WaitFor) использовать, например, критические секции ?

В потоке я обращаюсь к только к компоненту мемо формы, через Synchronize и очень редко. Вся работа потока заклчюатся в работе с сокетом посредством чтения/записи в TWinSocketStream и работы с процессами (перчисление процессов средствами JwaPsApi (Jedi), открытие, ожидание завершения (WaitForSingleObject) либо принудительное завершение процесса) и с событиями (TEvent). При этом потоки никакими данными не обмениваются, но синхронизируются между собой при помощи событий TEvent (я обрабатываю случаи когда поток ждет события которое уже уничтожено), таким образом я организую очередь клиентов, потому что сервер согласно своей функциональности не способен обрабытвать запросы нескольких клиентов одновременно. Код потока у меня обрабатывает исключения, а так же он весь напичкан проверками на Terminated, так что при запросе завршения он в любой точке работы закончит свою работу не дольше чем через 500 мс.

Как вы наверно догадались, моя программа достаточно большая, поэтому я не поместил ее сюда, а описал самые важные моменты ее реализации. На данный момент она сбоит примерно на каждом 6-ом клиенте.

Буду очень благодарен, если вы прочитаете хоть что-то из моей огромной писанины и поможете разобраться хоть в одном из вопросов/проблем. Если я разберусь во всем, то обещаю написать исчерпывающую статью о том, как работать в блокирующем режиме с TServerSocket.
PM MAIL   Вверх
dumb
Дата 23.8.2007, 22:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

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



Цитата(artymen @  23.8.2007,  21:43 Найти цитируемый пост)
если мне не поможет кто-то извне, я кончу психушкой.
ты кончишь психушкой. smile

1. да.
2. все, что начинается на OnClient и на OnThread - должно быть thread-safe.
3. отличается, хотя и наследник. НО. в TServerSocket используется пул потоков, т.е. при отключении клиента потоки не уничтожаются, а ждут повторного использования. OnThreadStart вызывается уже из Execute, поэтому инициализировать там можно далеко не все.
4. подробное протоколирование в файл каждого "чиха". функцию лога на критическую секцию.
5. TEvent - thread-safe. никаких крит.секций не нужно.

Цитата(artymen @  23.8.2007,  21:43 Найти цитируемый пост)
моя программа достаточно большая, поэтому я не поместил ее сюда, а описал самые важные моменты ее реализации.
именно поэтому ты и кончишь психушкой. smile
PM MAIL   Вверх
artymen
Дата 24.8.2007, 07:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодер



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

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



Спасибо ! Психушка тепреь от меня очень отдалилась !  smile  Щас учту эти моменты (особенно 2 и 3-ий, здесь то и заключается вся западня) и доложу о результатах.

И как же мне в обработчиках событий безпопасно обраться к форме, если там нет Synchronize ? Наверно придется через PostMessage.

PS. Насчет обмена данными между потоками. Забыл, что поток читает глобальную пременную, но это делается в Synchronize. Вряд ли это имеет значение, но все же. smile
PM MAIL   Вверх
Felan
Дата 24.8.2007, 07:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(artymen @  24.8.2007,  09:29 Найти цитируемый пост)
И как же мне в обработчиках событий безпопасно обраться к форме, если там нет Synchronize ? Наверно придется через PostMessage.

Вот здесь как раз критические секции.
Если у тебя есть объект на форме, который тебует изолированного доступа, то делаешь критическую секцию и методы доступа к объекту, которые будут работать через эту критическую секцию.

Цитата(artymen @  24.8.2007,  09:29 Найти цитируемый пост)

PS. Насчет обмена данными между потоками. Забыл, что поток читает глобальную пременную, но это делается в Synchronize. Вряд ли это имеет значение, но все же. smile 

Если у тебя к ней, кроме твоего потока, имеет доступ только поток VCL, но не имеет, а если еще один (например поток соединения сокета), то нужно делать ручную синхронизацию. Synchronize используется ИСКЛЮЧИТЕЛЬНО ДЛЯ СИНХРОНИЗАЦИИ С ПОТОКОМ VCL!!!

ЗЫЗ Странно вообще-то видеть такие вопросы в свете сказанной тобой фразы
Цитата(artymen @  23.8.2007,  22:43 Найти цитируемый пост)
Скажу сразу, что многопоточность я изучил достаточно досканально и уже настардался с нею
  smile 



--------------------
// Любая сложная система - это темный лес. Каждый в этом лесу протаптывает свои тропинки, по ним и бегает. Лишь изредка, сходя с них, мы находим много интересного, а порою и страшного.
PM MAIL WWW ICQ   Вверх
artymen
Дата 24.8.2007, 10:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодер



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

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



УРААА !!!  smile  Сервер рабоатет стабильно ! С меня статья  smile 

Цитата

ЗЫЗ Странно вообще-то видеть такие вопросы в свете сказанной тобой фразы

Все нормально, потому что:
1. К тем переменным не обращаются другие потоки, иначе бы я это сказал и не пихал бы смело в Synchronize.
2. Тут поток особенный, поэтому у меня вопросы/сомнения насчет традиционной работы с этим потоком.
PM MAIL   Вверх
artymen
Дата 24.8.2007, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодер



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

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



И еще последний вопрос насчет TWinSocketStream.WaitForData(). В справке написано 
Цитата

Call WaitForData to ensure that the socket connection is ready to read or write information. (Вызовите WaitForData, чтобы убедиться, что сокетное соединение готово к чтению или записи информации.)
 Это инициализирующая функция, т.е. ее достаточно вызвать только в начале работы с потоком ? Если да, то я с радостью уберу ее из оставшейся части кода, потому что о таймаутах я позаботился в вызовах read/write.
PM MAIL   Вверх
dumb
Дата 24.8.2007, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

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



WaitForData - ожидание приходящих данных. причем тут "write" - я не понял, так как она просто select на read-события сокета делает... нужна скорее для "ручного" вычитывания данных из сокета, нежели для  того, о чем написано в справке... есть подозрение, что ты ее можешь вообще убрать.
PM MAIL   Вверх
artymen
Дата 24.8.2007, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодер



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

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



Отлично, так и сделаю smile Ибо в клиенте я не использую ее и нормально работает.
PM MAIL   Вверх
artymen
Дата 24.8.2007, 16:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодер



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

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



Мда, убрал WaitForData'ы - стабильность исчезла  smile 
PM MAIL   Вверх
dumb
Дата 26.8.2007, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

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



Цитата(artymen @  24.8.2007,  17:49 Найти цитируемый пост)
убрал WaitForData'ы - стабильность исчезла
не должно быть такого(хотя наверняка трудно без кода говорить) - попробуй на место этих Wait'ов поставить просто Sleep с такими же значениями задержки.
PM MAIL   Вверх
artymen
Дата 26.8.2007, 20:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодер



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

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



Все нормально, это я накосячил. Я убрал wait'ы и забыл что далее, будучи увереным после wait'а, что данные пришли, через ReadBuffer читал, а таймаут я для этих операций маленький сделал, поэтому генерировалось исключение. smile
У меня теперь другой вопрос насчет Write метода. В справке очень неясно описана мелкая, но очень важная деталь:
Цитата

if the connection is too slow to transfer all the data, Write will return 0 (если соединение очень медленное для отправки всех данных, то Write вернет 0)
 Это означает, что от клиента не пришло за время таймаута всех TCP-пакетов подтверждений (тогда соединение должно разорваться, ведь TCP обеспечивает гарантированную доствку данныха), и они могут прийти потом, после того как я повторно пошлю? Что делать в такой ситуации ?
PM MAIL   Вверх
artymen
Дата 27.8.2007, 15:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодер



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

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



статья откладывается на неопределенный срок =)
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Сети"
Snowy
Poseidon
MetalFan

Запрещено:

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

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

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

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

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


 




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


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

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