![]() |
Модераторы: korob2001, ginnie |
![]() ![]() ![]() |
|
zerg13new |
|
|||
Новичок Профиль Группа: Участник Сообщений: 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 |
|||
|
||||
Pfailed |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 933 Регистрация: 19.7.2009 Репутация: 22 Всего: 39 |
Это что-то странное. Попробуйте проще:
|
||||
|
|||||
zerg13new |
|
|||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 25.3.2010 Репутация: нет Всего: нет |
пробывал и так, всё равно будет ошибка при выполнении программы. Вообще как я заметил, ошибка появляется как только хэш %clients становится глобальным. То есть я делал массив хэндлов и запихивал в них хэндлы push_ом без проблем, но как только обьявлял массив shared, то тут же появлялась эта ошибка |
|||
|
||||
DurRandir |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 335 Регистрация: 27.9.2009 Репутация: 14 Всего: 17 |
>use threads;
>use threads::shared; О нет, нет, нет |
|||
|
||||
zerg13new |
|
|||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 25.3.2010 Репутация: нет Всего: нет |
как насчёт обьяснить чего не нравится или есть ли какие предложения дельные ?? рассмотрю с удовольствием, а то я уже ![]() |
|||
|
||||
mvsgt |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 209 Регистрация: 27.3.2009 Репутация: 1 Всего: 1 |
"нет нет нет" работает нормально, только очень тормозит если злоупотреблять.
Почему бы не сделать простой форкающий сервер - модулей для *daemon* много. Добавлено через 3 минуты и 30 секунд
это непонятно что. и, кажется, с shared хэшами нельзя так рабоать вообще - только поэлементно. в инструкции про это что-то есть. |
|||
|
||||
zerg13new |
|
||||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 25.3.2010 Репутация: нет Всего: нет |
mvsgt,
извиняюсь, не заметил, но исправил в теме, этого конечно у меня в коде нет, это какой-то бред ) у меня так: %clients = { %clients , "$client_ip:$client_port" => $client } ; переписывание на $clients{"$client_ip:$client_port"} = $client ;
в оригинале я должен запустить этот сервер под Win, а с fork() у меня возникли какие-то проблемы с блокировками или буферизацией(только по очереди обменивались клиент и сервер) . думаешь с fork() оно будет работать лучше ?? Я не знаю разделение переменных между потоками и процессами в perl разные вещи ли !? и всё равно у меня вопрос будет " а как сделать глобальный хэш с дескрипторами!?" или вообще что-то глобальное, откуда любой процесс/поток может забрать нужный ему десриптор !? |
||||
|
|||||
mvsgt |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 209 Регистрация: 27.3.2009 Репутация: 1 Всего: 1 |
никак нельзя, я думаю. дескрипторы так не распространяются. А вот под windows как раз может и получиться - там форки тредами эмулируются. Но всё равно это муторно и ненадёжно. Надо ещё раз задачу обдумать. Может вообще нужно что-то типа comet.
|
|||
|
||||
DurRandir |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 335 Регистрация: 27.9.2009 Репутация: 14 Всего: 17 |
Основная проблема с потоками - вам _кажется_, что всё очевидно. А это не так. Вот вы помянули некие блокировки (для форка) - а для потоков они вам, видимо, и не нужны? Ну, флаг в руки. Для эффективного использования сетевого I/O - посмотрите на AnyEvent/EV - последние версии вполне собираются под strawberry perl.
|
|||
|
||||
zerg13new |
|
|||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 25.3.2010 Репутация: нет Всего: нет |
DurRandir,
пока что я исхожу из того, что: 1. я могу передать в поток хэндл сокета как аргумент (вначале я просто передавал аргументом потоку именно хэндл $client и поток с ним нормально работал, следовательно в поток передать хэндл можно и он будет действительный и с ним работает ) 2. я могу создать расшаренный для потоков хэш (я указывал хэндл для хэша как "$client" и он его спокойно записывал, и поток читал из хэша, но хэндлом уже не считал(вдать изменяет контекст из-за кавычек), а потому преполагаю пункт 1) ТО наверное можно как-то совместить: создав что-то глоабльное для всех потоков, откуда потоки смогут спокойно читать, к примеру попытать хэш. И только из-за этих 2х пунктов я верю, что я просто чего-то недопонимаю и потому никак не могу записать нормально хэндл в хэш, и жду от вас победы над моей проблемой ![]() |
|||
|
||||
mvsgt |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 209 Регистрация: 27.3.2009 Репутация: 1 Всего: 1 |
в линуксовом перле потоки вообще есть?
|
|||
|
||||
ginnie |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1287 Регистрация: 6.1.2008 Где: Москва Репутация: 38 Всего: 49 |
zerg13new, быстрым поиском нашел тему на PerlMonks о доступе к сокетам из потоков. Посмотрите, может найдете что-нибудь полезное. Сам я подобными задачами не занимался, так что конкретно ничем помочь не могу.
Это сообщение отредактировал(а) ginnie - 25.3.2010, 18:49 -------------------- Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг) |
|||
|
||||
zerg13new |
|
|||
Новичок Профиль Группа: Участник Сообщений: 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. |
|||
|
||||
gcc |
|
||||
![]() Агент алкомафии ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 2691 Регистрация: 25.4.2008 Где: %&й Репутация: 1 Всего: 17 |
может хэш сделать:
http://perldoc.perl.org/perlref.html#Making-References
Это сообщение отредактировал(а) gcc - 25.3.2010, 19:54 |
||||
|
|||||
zerg13new |
|
|||
Новичок Профиль Группа: Участник Сообщений: 11 Регистрация: 25.3.2010 Репутация: нет Всего: нет |
gcc,
спасибо, сделал уже так: $clients{ "$client_ip:$client_port" } = *client{IO}; # add new socket to %client да вот только не знаю как же извлечь то хэндл (не тот либо неопределно значние либо ещё что-нибудь) для syswrite( (вот уж как здесь не изголяюсь с обзыванием), "hi, how are you??") || die ":$! _ $@"; есть идеи как излечь из хэша ?? а то он не хочет... |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Perl" | |
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Perl: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |