主页
Top.Mail.Ru Yandeks.Metrika
论坛:“系统”;
当前存档: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 "вручную", он вдруг "оживает", и перед остановкой выбрасывает в сеть последний полученный пакет. Т.е. пакеты он на самом деле получает, но отправлять их не хочет. Звучит глупо, но это так. И еще один ма-а-аленький вопрос. ПОЧЕМУ НЕ РАБОТАЕТ " 试试......除外". Эта конструкция не срабатывала и тогда, когда эта служба была простым приложением.



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.63 MB
时间:0.055 c
1-31858
助步车
2002-09-29 00:39
2002.10.10
COM,接口


1-31809
Starkom
2002-10-02 11:26
2002.10.10
帮助处理故障。


14-31987
_
2002-09-16 15:50
2002.10.10
http://invega.by.ru


14-31996
变态
2002-09-15 21:57
2002.10.10
че-то я не понимаю


1-31829
pvasya
2002-09-28 09:53
2002.10.10
EOleException





南非荷兰语 阿尔巴尼亚人 阿拉伯语 亚美尼亚 阿塞拜疆 巴斯克 白俄罗斯 保加利亚语 加泰罗尼亚 简体中文 中国(繁体) 克罗地亚 捷克 丹麦语 荷兰人 英语 爱沙尼亚语 菲律宾人 芬兰 法文
加利亚西语 格鲁吉亚语 德语 希腊语 海地克里奥尔语 希伯来语 印地语 匈牙利 北日耳曼语 印度尼西亚人 爱尔兰语 意大利语 日本性玩偶 韩语 拉脱维亚 立陶宛 马其顿 马来语 马耳他语 挪威语
波斯语 波兰语 葡萄牙语 罗马尼亚 俄语 塞尔维亚 斯洛伐克 斯洛文尼亚 西班牙语 斯瓦希里 瑞典语 泰国人 土耳其 乌克兰 乌尔都语 越南人 威尔士语 意第绪语 孟加拉 波斯尼亚
宿务 世界语 古吉拉特语 豪萨语 苗族 伊博 爪哇 卡纳达语 高棉 老挝 拉丁语 毛利 马拉 蒙古人 尼泊尔 旁遮普 索马里 泰米尔人 泰卢固语 约鲁巴语
祖鲁
英文 Французский Немецкий Итальянский Португальский 俄文 Испанский