Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.10.10;
Скачать: CL | DM;

Вниз

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

 
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;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.013 c
3-31641
Виталий Панасенко
2002-09-18 14:50
2002.10.10
Почему глючит Дятел


14-31953
MIFI
2002-09-14 20:38
2002.10.10
Для контроля над ACTIVEX кроме regsvr32


14-31947
buhat
2002-09-14 17:18
2002.10.10
Где достать?


1-31841
Mazenrat
2002-09-28 15:39
2002.10.10
Страсти по SetMenuItemBitmaps.


1-31840
PaRL
2002-09-28 16:58
2002.10.10
---|Ветка была без названия|---