Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Система";
Текущий архив: 2002.10.10;
Скачать: [xml.tar.bz2];

Вниз

Загадочная служба   Найти похожие ветки 

 
Wazowski   (2002-07-29 16:49) [0]

Написал, с горем пополам, службу для пересылки UDP пакетов с одной машины на другую. Этакий маршрутизатор. Вот только ведет он себя загадочно. Если есть кому передать пакет дальше - все в порядке. Если же некому принять пакет (например выключена машина адресата, или что-то в таком духе) - дает ошибку записи в поток, и вырубается. Однако самое интерестное не в этом. С этой проблемой я сталкивался и раньше.Правда решить ее способом, который катил в обычной программе, не удалось. Ну не поддерживают службы процедуру ProcessMessages хоть ты лопни. Так вот. После сбоя служба вылетает, но консоль управления службами говорит, что все нормально - ваша служба работает. Исправить все удается только после перезапуска службы вручную. (Пробовал я менять установки службы - не хочет она сама перезапускаться после збоя. Похоже Windows даже "не знает". что служба сбойнула и уже не работает). Помогите чем можете. Нужно-то всего, отловить возникновение ошибки записи в поток.


 
Fiend   (2002-07-30 09:57) [1]

Жаль увидел ваш вопрос уже когда надо было уходить домой, но сегодня вспомнил и решил ответить, может вы прочтете.

Первый вопрос: зачем вам нужна ProcessMessages. Уверен можно обойтись без. У меня есть сложная многопоточная служба. Так вот пока она в процессе написания и отладки была простым приложением, то я действительно испоьзовал ProcessMessages в некоторых местах основного потока. Но когда переделал в службу, то эта необходимость отпала сама собой. Я сделал так: основной поток службы, который выполняется в OnExecute, содержит всего одну строку CRService.ServiceThread.ProcessRequests(true);, т.е. основной поток просто висит и ждёт системного сообщения (Паза, стоп, рестарт). Таки образом, мой поток всегда сможет и завершится и запуститься.

Вопрос второй: как вы позволили себе запустить службу, которая принципиально способна завалить систему т.к. она есть процесс системы, если она у вас не отлажена до нуля? Надо было конечно всё откатать на обычном приложении.

Третий: зачем допускать мысль о самом принципе перезапуска службы в случае аварии??? Это вы наверно у Microsoft насмотрелись? в MS SQL Server? Если да, то не забывайте, что там немного другой механизм. Там служба сама себя не перезапускает в случае аварии, а есть на то Server Agent, тоже служба, которая и смотрит, если сервер свалился, то она его перезапустит.

с наилучшими!


 
Wazowski   (2002-07-31 12:26) [2]

Все бы это хорошо, только не помогло :-(
Как помирала служба тихонько - так и помирает. Возникает интерестный эффект. Маршрутизатор вроде пакеты принимает (после збоя), так как программы-клиенты сообщают об удачной отправке, но дальше их не передает. И что совсем загадочно - при попытке перезапустить службу из MMC "вручную", он вдруг "оживает", и перед остановкой выбрасывает в сеть последний полученный пакет. Т.е. пакеты он на самом деле получает, но отправлять их не хочет. Звучит глупо, но это так. И еще один ма-а-аленький вопрос. ПОЧЕМУ НЕ РАБОТАЕТ " try...except". Эта конструкция не срабатывала и тогда, когда эта служба была простым приложением.


 
Digitman   (2002-07-31 13:24) [3]

блок try...except вовсе и не обязан работать ожидаемым тобой образом везде, куда только его не "ткни"

Приводи конкретный пример того случая, когда блок не работает


 
Fiend   (2002-07-31 17:08) [4]

То Wazowski

Абсолютоно согласен с Digitman насчёт try except.
У меня тоже была в моём сервисе ситуация когда этот блочёк "не срабатывал". Но как потом оказалось, ошибка у меня возникала вовсе не внутри него, а уже после него, на совершенно безобидных инструкциях. В моём случае дело было в синхронизации, кстати Digitman участвовал в моей ветке по тому вопросу. У меня получалось так, что когда поступало сообщение сервису об остановке службы дочерние потоки не успевали еще остановиться(хотя я сделал вроде всё чтобы они завершились), а я уже выгружал используемые ими ресурсы. Это происходило после блока try except, и достаточно хаотично, чтобы ввести меня в полное заблуждение. В итоге я использовал свою любимую функцию BEEP для отладки процесса остановки сервиса. Просто тупо брал и ставил ее сначала в одно место и останавливал несколько раз внимательно слушая динамик, потом в другое и тоже самое. В результате двухдневных слуховых и умственных напряжений засёк в чем дело.

Ну и на последок: очень трудно вам чем то помочь, как вы сами наверное понимаете, когда не видно исходников. Мыльните, может чем и помогу. Обещаю исходники не продавать и не дарить, а уничтожить после просмотра. :))))

С Наилучшими!


 
Digitman   (2002-07-31 17:31) [5]

>Автору

Промедлил с кодом - сразу же угодил в "Потрепаться")
Модераторы знают свое дело !) Молодцы !


 
Wazowski   (2002-08-01 11:39) [6]

По многочисленным просьбам выкладываю код:

procedure TUDPProxy.ProxyAction(RemAddr:String;ActionString:String;Sender: TObject);
var
MyStream: TMemoryStream;
TmpStr: String;
Begin
NMUDP1.ReportLevel := Status_Basic;
NMUDP1.RemoteHost := RemAddr;
NMUDP1.RemotePort := 6767;
TmpStr := ActionString;
MyStream := TMemoryStream.Create;
try
MyStream.Write(TmpStr[1], Length(TmpStr));
!*! NMUDP1.SendStream(MyStream);
except
on EWriteError do
begin
MyStream.Free;
end;
else MyStream.Free;
end;
NMUDP1.RemotePort := 7000;
end;

procedure TUDPProxy.NMUDP1DataReceived(Sender: TComponent;
NumberBytes: Integer; FromIP: String; Port: Integer);
var
MyStream: TMemoryStream;
TmpStr: String;
begin
MyStream := TMemoryStream.Create;
try
NMUDP1.ReadStream(MyStream);
SetLength(TmpStr,NumberBytes);
MyStream.Read(TmpStr[1],NumberBytes);
finally
MyStream.Free;
SenderIP:=FromIP;
end;
Sleep(200);
try
ProxyAction(GetAddr(TmpStr),GetMessage(TmpStr),nil);
finally
{тут был код сигналов для пользователя, но в случае службы он утратил свое значение}
end;
end;


Это две основные процедуры, которые я перенес, почти без изменений, из одной своей программы. Вернее это был прототип моей службы, только в виде приложения. Все это успешно работало на Win2000 Server в течении 5 месяцев. Там упоминается еще пара функций, но их названия сами за себя говорят. Это просто функции работы со строкой, а посему я их сюда не выкладывал.
Ошибка наблюдалась в строке помеченной !*!, в случае отсутствия клиентской программы-получателя "на том конце провода". Возникает ошибка записи в поток.
Буду рад выслушать любые предложения, и стерпеть любую критику :)


 
Digitman   (2002-08-01 15:01) [7]

Подозреваю, что проблема та же , что и вызывает массу вопросов по TClientSocket/TServerSocket : непонимание особенностей работы гнезда в асинхронном режиме.

Сам никогда не пользовался компонентами из FastNet (в частности - NMUDP) из-за отсутствия исх.текстов (это - принцип), но склонен с достаточной долей уверенности предположить, что режим работы гнезда, управляемого объектом NMUDP - именно асинхронный. А это значит, что никакой try..except со вложенным в него send-методом работать ожидаемым тобой образом не будет. Гнездовые транспортные события возникают асинхронно, и "ловить" их (в т.ч. и в 1-ю очередь - события, фиксирующие отказ транспортного канала по тем или иным причинам) нужно в соответствующих событиях объекта NMUDP, а не так, как это выглядит в приведенном коде.

Непонятно кр.того, зачем в блоке except нужно обязательно изменять номер порта : исключение может быть любым, в т.ч. и не связанным с транспортом. Кстати, EWriteError, как помнится, как раз с транспортом-то совсем и не связано : мало ли почему не удалось в поток записать данные... поток - это просто сам по себе поток .. как это с транспортом-то гнездовым связано ?


 
Waxowski   (2002-08-02 11:46) [8]

Хочу выразить благодарность всем, кто откликнулся на мой зов о помощи.
Особую признательность хотелось бы выразить Fiend, который собственно и предложил вариант решения проблеммы.
А ошибка возникала, как раньше, из-за того что NMUDP все еще пытался отправить пакет по адресу, где его никто не примет, а программа уже уничтожала поток отправки.Так что мы вставили небольшую задержку с опросом состояния сервиса и отправки, и все встало на свои места.
Самое обидное, что все эти процедуры - лишь немного измененные для моих нужд примеры из Delphi. Наглядность в них конечно присутствует, но на поверку оказались они весь сыроваты, как видите.
Ну да нияего - на ошибках учатся.
Еще раз огромное всем спасибо.


 
Wazowski   (2002-08-02 11:53) [9]

>>Digitman
Как раз транспорт тут и ни причем. Как известно протокол UDP (в отличие от TCP) работает без подтверждения доставки пакетов, потому я использую именно его. И то что ошибка возникает именно на уровне TStream это я вычислил сразу. Но вот дальше меня смутило то что под Win95\98\Me этот код работает, а под Win2000 - нет.


 
Digitman   (2002-08-02 12:10) [10]

>Wazowski

Ну так я и говорю : проблема-то - именно в особенностях асинхронного режима работы гнезда как такового, а не в отличиях транспорта в режимах SOCK_STREAM и SOCK_DGRAM гнезда. Все сходится - ты запустил асинхронную операцию и , не дождавшись ее окончательных результатов (не анализируя событий, сообщающих об успехе или неуспехе операции), уничтожил ресурс, от которого зависит работа этой асинхронной операции, в дан.случае - TStream.


 
Wazowski   (2002-08-02 12:20) [11]

>>Digitman
Вот уж точно!
Просто я зациклился на том что ошбок при передаче быть не может-пакет отправлен, а дальше нас не волнует, что с ним. А оно оказывается стоило подождать.
Только все таки непонятно мне почему-же в Милениуме это все работает????? Может я тупой какой, или не понимаю чего-то?


 
Fiend   (2002-08-02 12:42) [12]

То Wazowski

Во всём виноват БИЛЛИ!

У моего тов. есть програ на VC++, так вот она под NT 4 отлично работает а под W95, W98 - болт. Шо тока ни делали.....
Даже перекомпилили ее под виндой 98, а всё равно болт, болтом и отсался :)))))))


 
Digitman   (2002-08-02 13:33) [13]

>Wazowski

Думаю, что это - из-за отличающихся реализаций в коде спецификации Winsock.

При асинхронном режиме полагаться следует исключительно на события и правильную (в соответствии со спецификацией Winsock) их обработку. Либо - не использовать асинхронный режим, а воспользоваться синхронным, перенеся логику в доп.поток



Страницы: 1 вся ветка

Форум: "Система";
Текущий архив: 2002.10.10;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.008 c
1-31743
Magic
2002-10-01 12:42
2002.10.10
Окно перед программой


1-31680
Юрий Зотов
2002-09-28 23:07
2002.10.10
Странное поведение дебаггера D5 под XP


1-31826
autumn_orion
2002-09-27 17:04
2002.10.10
Перевод строки символов из win в dos кодировку.


14-32013
RV
2002-09-17 16:27
2002.10.10
дайте если есть и нежалко инсталляцию паскаля > 4 версии, плз


1-31673
Mic_2000
2002-09-27 16:25
2002.10.10
Добавление компонент во время выполнения программы





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский