Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.221.222.47] |
|
Сообщ.
#1
,
|
|
|
Всем привет!
Дали задачу написать многопоточный демон, который слушает какой-либо порт и приняв информацию на него работает с ней(а это суть рекурсивный поиск grep). Инфу полученную он отдает клиенту, а закончив работу с поиском должен освободить сокет от лишнего мусора, но не закрывать его и не умирать. Задачу необходимо по условию решить не обращаясь к "самостоятельным" модулям СПАНа, а сделать все ручками. И вот что я наваял: #!/usr/bin/perl -- # SERVER use strict; use threads; use IO::Socket; use Net::hostent; use POSIX; my $pid = fork; exit if $pid; # ВЫКЛЮЧАЮ РОДИТЕЛЬСКИЙ ПРОЦЕСС, ЧТОБЫ РАБОТАЛ ДЕМОН die "Could not fork: $!\n" unless defined($pid); my $exit = 0; # ЗАКРЫВАЮ ДЕСКРИПТОРЫ for my $handle(*STDIN, *STDOUT, *STDERR) { open($handle, "+<", "/dev/null") or die "cant reopen $handle to /dev/null: $!\n"; } POSIX::setsid() or die "Cant create a new session\n"; my $die_flag = 0; # ЭТА ПЕРЕМЕННАЯ ОПРЕДЕЛЯЕТ СРОК ЖИЗНИ ДЕМОНА $SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&signal_handler; $SIG{PIPE} = 'IGNORE'; # САМ СЕРВЕР my $server = new IO::Socket::INET(LocalPort => 6666, TYPE => SOCK_STREAM, ReuseAddr => 1, Listen => 10 ) or die $@; # РАБОТА, КОТОРУЮ ДОЛЖЕН ИСПОЛНЯТЬ СЕРВЕР sub handle_connection { my $socket = shift; my $output = shift || $socket; my $usage = "\nUsage:\nfind \'search string\' /where/to/find\n\n"; print $output $usage; my ($where, $what); while (<$socket>) { if (/^find\s+\'(.+)\'\s+(.+)/) { $what = $1; $where = $2; } elsif (/^(help|\?)/) { print $output $usage; } else { print $output "Bad pattern!:\t$_\n$usage"; #last; } while(my $line = `grep -r \'$what\' $where`) { next if ($line =~ /grep:/); # means 'permission denied' print $output $line; last if $exit; } print "Search done\n\n"; $exit = 1; last if $exit; } } until ($die_flag) { # РАБОТА С ПОДКЛЮЧЕНИЯМИ К СОКЕТУ ДОЛЖНА ПО ИДЕЕ ЗАВЕРШИТЬСЯ КОРРЕКТНО, ЕСЛИ $die_flag = 1 while (my $socket = $server->accept) { async(\&handle_connection, $socket)->detach; # В detach по идее сокет "очищается", но на самом деле нет, } } sub signal_handler { $exit = 1; $die_flag = 1; } Подключившись nc localhost 6666, я вызываю команду find 'search string' /path/to , в итоге запускается grep. При досрочном закрытии клиента CTRL-C мой процесс grep остается в системе и растет в памяти, прямопропорционально количеству подключенных клиентов, демон тоже растет в объеме... Сам думаю что конструкция async(\&handle_connection, $socket)->detach; Надеюсь, что расписал проблему понятно.... - при закрытии подключения со стороны клиента посредством CTRL_C - grep остается в списке рабочих процессов... ну и тп... Оч прошу помогите разобраться пож-ста! |
Сообщ.
#2
,
|
|
|
На мой взгляд вот здесь несчастье начинается:
while (<$socket>) {.. В этом вайле нет работы с ресурсами. Т.е. я не увидел места, где осуществляется контроль работы. |
Сообщ.
#3
,
|
|
|
Цитата Nadz Goldman @ На мой взгляд вот здесь несчастье начинается: while (<$socket>) {.. В этом вайле нет работы с ресурсами. Т.е. я не увидел места, где осуществляется контроль работы. Не совсем понятно, т.е. если я на удаленном хосте вышел из сессии соединения с помощью CTRL-C, то это можно как-то узнать на сервере? Ведь суть соединение оборвано - и есть информация, ресурс. Или как-то иначе? |
Сообщ.
#4
,
|
|
|
Да просто изначально не так подошел к проблеме.
Да, конечно это можно узнать. Добавлено Примитивно, но просто -- форкаем процесс на поиск, форкаем на работу с клиентом, где ждем команды "стоп". |
Сообщ.
#5
,
|
|
|
Цитата Nadz Goldman @ Добавлено Примитивно, но просто -- форкаем процесс на поиск, форкаем на работу с клиентом, где ждем команды "стоп". Добавил форк грепа, но греп в процессах после CTRL-C остается! Что сейчас не так? .... my $pid2 = fork; exit if $pid2; die "Could not fork: $!\n" unless defined($pid2); while (my $line = `grep -r \'$what\' $where`) && defined($pid2)) { next if ($line =~ /grep:/); # means 'permission denied' print $output $line; last if $exit; } ... |
Сообщ.
#6
,
|
|
|
Да при чем здесь контрол-цэ?!!
Контрол-цэ тогда обрабатывай в своей программе и при обнаружении таковой отсылай команду серверу "стоять!" и только после этого завершай программу-клиент. |