Модераторы: korob2001, ginnie

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> проблема записи хэндлов в глоабальный хэш ? помогите решить проблему 
V
    Опции темы
zerg13new
Дата 25.3.2010, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 25.3.2010

Репутация: нет
Всего: нет



народ, ОЧЕНЬ нужна помощь, так как я уже устал и не понимаю совсем ничего
пишу в linux на perl и цель программы такова: создать сервер, кот принимал бы соединения от клиентов и мог посылать любому выбранном на сервере клиенту сообщение. пишу под консоль, итак код той части что не получается:

 # my server
      2 # 2010.03.05
      3 
      4 #!/usr/bin/perl -w
      5 
      6 use strict;
      7 use IO::Socket;
      8 #use Thread;
      9 use threads;
     10 use threads::shared;
     11 #use POSIX 'WNOHANG'; # for SIGNAL
     12 use constant BUFSIZE => 1024;
     13 
     14 
     15 my %clients :shared;
     16 my( $addr, $port );
     17 
     18 
     19 $addr = &get_ip(); # get IP from interface
     20 
     21 # get port
     22 print "enter port: ";
     23 while( <STDIN> ) {
     24         chomp($_);
     25         $port = $_;
     26         if ( /[0-9]{4,5}/ && $_ > 1024 ) { last; }
     27         print "either wrong value or port is deny, enter new value: ";
     28 }
     29 
     30 my $server = IO::Socket::INET -> new( LocalAddr => $addr,
     31                                         LocalPort => $port,
     32                                         Listen => 255,
     33                                         Type => SOCK_STREAM,
     34                                         Proto => 'tcp',
     35                                         Reuse => 1 );
     36 die "can't create, bind or listen: $!\n" unless $server ;
     37 print "socket OK\n bind OK\n listen OK\n Server started at $addr:$port\n";
     38 warn "Server ready. Waiting for connections... \n";
     39 
     40 threads -> create( \&to_client ) || die "$! \n"; # STDIN
     41
     42 # start threads to treat querys
     43 while( my $client = $server -> accept ) {
     44         my $client_ip = $client -> peerhost();
     45         my $client_port = $client -> peerport();
     46         my $tmp = "$client_ip:$client_port";
     47 
     48        %clients = { %clients , "$client_ip:$client_port"  => $client } ; # add new socket to %client ИМЕННО ЗДЕСЬ
# здесь никакого кода, просто пустота
     56 syswrite( $clients{ "$client_ip:$client_port" }, "hi, how are you??") || die ":$! _ $@";
     57 #foreach my $q ( keys %clients ) { print "debug0: $q\n"; }
     58         print "got a connection from: $client_ip:$client_port $client\n";
     59         $client -> autoflush;
     60 
     61         threads -> create( \&from_client, $client, $client_ip, $client_port ) || die "$! \n"; #STDOUT
     62 
     63 }
     64 exit 0;
     65 

В итоге я получу ошибку "Invalid value for shared scalar at server.pl line 48, <STDIN> line 1."
Хотелось бы прочитать совет спецов, показывающий наглядно как положить мне хэндл сокета $client в расшареный хэш %clients и как потом его оттуда правильно извлечь, чтобы он считался хэндлом. Если не сложно, то не отказался бы и от обьяснений где и почем же я балбес. Я честно пробывал множество всевозможных ссылок, разыменований, читал документацию типо ссылка на документацию по shared но ничего толкового не получилось.

Это сообщение отредактировал(а) zerg13new - 25.3.2010, 16:48
PM MAIL   Вверх
Pfailed
Дата 25.3.2010, 14:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 22
Всего: 39



Цитата

%clients = { %clients , $clients{ "$client_ip:$client_port" } = $client } ;


Это что-то странное.
Попробуйте проще:
Код

$clients{"$client_ip:$client_port"} = $client;



--------------------
PM MAIL   Вверх
zerg13new
Дата 25.3.2010, 15:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 25.3.2010

Репутация: нет
Всего: нет



Цитата(Pfailed @  25.3.2010,  14:08 Найти цитируемый пост)
1:$clients{"$client_ip:$client_port"} = $client;

пробывал и так, всё равно будет ошибка при выполнении программы.
Вообще как я заметил, ошибка появляется как только хэш %clients становится глобальным. То есть я делал массив хэндлов и запихивал в них хэндлы push_ом без проблем, но как только обьявлял массив shared, то тут же появлялась эта ошибка
PM MAIL   Вверх
DurRandir
Дата 25.3.2010, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 14
Всего: 17



>use threads;
>use threads::shared;

О нет, нет, нет
PM   Вверх
zerg13new
Дата 25.3.2010, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 25.3.2010

Репутация: нет
Всего: нет



Цитата(DurRandir @ 25.3.2010,  15:57)
>use threads;
>use threads::shared;

О нет, нет, нет

как насчёт обьяснить чего не нравится или есть ли какие предложения дельные ?? рассмотрю с удовольствием, а то я уже  smile 
PM MAIL   Вверх
mvsgt
Дата 25.3.2010, 16:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 209
Регистрация: 27.3.2009

Репутация: 1
Всего: 1



"нет нет нет" работает нормально, только очень тормозит если злоупотреблять.

Почему бы не сделать простой форкающий сервер - модулей для *daemon*  много.

Добавлено через 3 минуты и 30 секунд
Код

48        %clients = { %clients , $clients{ "$client_ip:$client_port" } = $client } ; # add new socket to %client ИМЕННО ЗДЕСЬ


это непонятно что. 
и, кажется, с shared хэшами нельзя так рабоать вообще - только поэлементно. в инструкции про это что-то есть.
PM MAIL   Вверх
zerg13new
Дата 25.3.2010, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 25.3.2010

Репутация: нет
Всего: нет



mvsgt
Цитата(mvsgt @  25.3.2010,  16:38 Найти цитируемый пост)
  %clients = { %clients , $clients{ "$client_ip:$client_port" } = $client } ; # add new socket to %client ИМЕННО ЗДЕСЬ

извиняюсь, не заметил, но исправил в теме, этого конечно у меня в коде нет, это какой-то бред )
у меня так:  %clients = { %clients , "$client_ip:$client_port"  => $client } ; 
переписывание на $clients{"$client_ip:$client_port"}  = $client  ;

Цитата(mvsgt @  25.3.2010,  16:38 Найти цитируемый пост)
Почему бы не сделать простой форкающий сервер - модулей для *daemon*  много.

в оригинале я должен запустить этот сервер под Win, а с fork() у меня возникли какие-то проблемы с блокировками или буферизацией(только по очереди обменивались клиент и сервер) . думаешь с fork() оно будет работать лучше ?? Я не знаю разделение переменных между потоками и процессами в perl разные вещи ли !?
и всё равно у меня вопрос будет " а как сделать глобальный хэш с дескрипторами!?" или вообще что-то глобальное, откуда любой процесс/поток может забрать нужный ему десриптор !?
PM MAIL   Вверх
mvsgt
Дата 25.3.2010, 17:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 209
Регистрация: 27.3.2009

Репутация: 1
Всего: 1



никак нельзя, я думаю. дескрипторы так не распространяются. А вот под windows как раз может и получиться - там форки тредами эмулируются. Но всё равно это муторно и ненадёжно. Надо ещё раз задачу обдумать. Может вообще нужно что-то типа comet.
PM MAIL   Вверх
DurRandir
Дата 25.3.2010, 18:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 14
Всего: 17



Основная проблема с потоками - вам _кажется_, что всё очевидно. А это не так. Вот вы помянули некие блокировки (для форка) - а для потоков они вам, видимо, и не нужны? Ну, флаг в руки. Для эффективного использования сетевого I/O - посмотрите на AnyEvent/EV - последние версии вполне собираются под strawberry perl.
PM   Вверх
zerg13new
Дата 25.3.2010, 18:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 25.3.2010

Репутация: нет
Всего: нет



DurRandir
пока что я исхожу из того, что:
1. я могу передать в поток хэндл сокета как аргумент (вначале я просто передавал аргументом потоку именно хэндл $client и поток с ним нормально работал, следовательно в поток передать хэндл можно и он будет действительный и с ним работает  )
2. я могу создать расшаренный для потоков хэш (я указывал хэндл для хэша как "$client" и он его спокойно записывал, и поток читал из хэша, но хэндлом уже не считал(вдать изменяет контекст из-за кавычек), а потому преполагаю пункт 1)
 ТО наверное можно как-то совместить: создав что-то глоабльное для всех потоков, откуда потоки смогут спокойно читать, к примеру попытать хэш. И только из-за этих 2х пунктов я верю, что я просто чего-то недопонимаю и потому никак не могу записать нормально хэндл в хэш, и жду от вас победы над моей проблемой  smile  (естественно сам я не бездействую)
PM MAIL   Вверх
mvsgt
Дата 25.3.2010, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 209
Регистрация: 27.3.2009

Репутация: 1
Всего: 1



в линуксовом перле потоки вообще есть?
PM MAIL   Вверх
ginnie
Дата 25.3.2010, 18:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



zerg13new, быстрым поиском нашел тему на PerlMonks о доступе к сокетам из потоков. Посмотрите, может найдете что-нибудь полезное. Сам я подобными задачами не занимался, так что конкретно ничем помочь не могу.

Это сообщение отредактировал(а) ginnie - 25.3.2010, 18:49


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
zerg13new
Дата 25.3.2010, 19:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 25.3.2010

Репутация: нет
Всего: нет



mvsgt
безусловно, как и в виндовой версии strawberry perl

ginnie
спасибо, прочёл,  попробуем обмозговать.. А вообще этот блог читается на одном дыхании как художественная книжка, здорово и эмоционально написано ))

кстати вот попробывал ещё такой вариант:
 $clients{ "$client_ip:$client_port" } = *client; # add new socket to %client
print ref($client) . "++ $client\n";
49(номер строки)  syswrite( *{$clients{"$client_ip:$client_port"}}{IO}, "hi, how are you??") || die ":$! _ $@";

вывод:
IO::Socket::INET++ IO::Socket::INET=GLOB(0x8a399d8)
Can't use string ("*main::client") as a symbol ref while "strict refs" in use at server.pl line 49, <STDIN> line 1.

PM MAIL   Вверх
gcc
Дата 25.3.2010, 19:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Агент алкомафии
****


Профиль
Группа: Участник
Сообщений: 2691
Регистрация: 25.4.2008
Где: %&й

Репутация: 1
Всего: 17



может хэш сделать:

Код

my %dispatch = (
  foo => *foo{IO},
  bar => *bar{IO},
);



http://perldoc.perl.org/perlref.html#Making-References
Цитата

#

A reference can be created by using a special syntax, lovingly known as the *foo{THING} syntax. *foo{THING} returns a reference to the THING slot in *foo (which is the symbol table entry which holds everything known as foo).

   1. $scalarref = *foo{SCALAR};
   2. $arrayref = *ARGV{ARRAY};
   3. $hashref = *ENV{HASH};
   4. $coderef = *handler{CODE};
   5. $ioref = *STDIN{IO};
   6. $globref = *foo{GLOB};
   7. $formatref = *foo{FORMAT};

All of these are self-explanatory except for *foo{IO} . It returns the IO handle, used for file handles (open), sockets (socket and socketpair), and directory handles (opendir). For compatibility with previous versions of Perl, *foo{FILEHANDLE} is a synonym for *foo{IO} , though it is deprecated as of 5.8.0. If deprecation warnings are in effect, it will warn of its use.

*foo{THING} returns undef if that particular THING hasn't been used yet, except in the case of scalars. *foo{SCALAR} returns a reference to an anonymous scalar if $foo hasn't been used yet. This might change in a future release.

*foo{IO} is an alternative to the *HANDLE mechanism given in "Typeglobs and Filehandles" in perldata for passing filehandles into or out of subroutines, or storing into larger data structures. Its disadvantage is that it won't create a new filehandle for you. Its advantage is that you have less risk of clobbering more than you want to with a typeglob assignment. (It still conflates file and directory handles, though.) However, if you assign the incoming value to a scalar instead of a typeglob as we do in the examples below, there's no risk of that happening.

   1. splutter(*STDOUT); # pass the whole glob
   2. splutter(*STDOUT{IO}); # pass both file and dir handles
   3.
   4. sub splutter {
   5. my $fh = shift;
   6. print $fh "her um well a hmmm\n";
   7. }
   8.
   9. $rec = get_rec(*STDIN); # pass the whole glob
  10. $rec = get_rec(*STDIN{IO}); # pass both file and dir handles
  11.
  12. sub get_rec {
  13. my $fh = shift;
  14. return scalar <$fh>;
  15. }


Это сообщение отредактировал(а) gcc - 25.3.2010, 19:54
PM WWW ICQ Skype GTalk Jabber   Вверх
zerg13new
Дата 25.3.2010, 20:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 25.3.2010

Репутация: нет
Всего: нет



gcc
Цитата(gcc @  25.3.2010,  19:53 Найти цитируемый пост)
может хэш сделать:КодincludeSyntax('perl');my %dispatch = (  foo => *foo{IO},  bar => *bar{IO},);

спасибо, сделал уже так:
 $clients{ "$client_ip:$client_port" } = *client{IO}; # add new socket to %client
да вот только не знаю как же извлечь то хэндл (не тот либо неопределно значние либо ещё что-нибудь) для
syswrite( (вот уж как здесь не изголяюсь с обзыванием), "hi, how are you??") || die ":$! _ $@";
есть идеи как излечь из хэша ?? а то он не хочет...
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1139 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.