Форум: "Система";
Текущий архив: 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