Em 3 de maio de 2011 15:59, Solli Honorio <shono...@gmail.com> escreveu:
> > > 2011/5/3 Andre Carneiro <andregarciacarne...@gmail.com> > >> Salve Monges! >> >> >> Estou com uns problemas com Sockets que mesmo fuçando bastante eu não >> consegui resolver. Os sockets tanto do lado do servidor quanto do lado do >> cliente estão ok, e isso significa: >> >> - O 'socket' do lado do 'client' escreve coisas no socket >> - O 'socket' do lado do server lê coisas do Socket; >> >> Agora eu preciso que o socket do lado do servidor envie os resultados como >> mensagens de erros e dados, de maneira geral, para o client. O que tá >> rolando agora: >> >> >> SERVER: >> >> <code> >> use strict; >> use warnings; >> use IO::Socket::INET >> use Daemon::Generic; >> use feature qw/ say switch /; >> . >> . >> . >> #configuração >> . >> . >> . >> my $usock = IO::Socket::INET->new ( >> Type => SOCK_STREAM , >> LocalAddr => $config_socket->{ SocketBind }, >> LocalPort => $config_socket->{ SocketPort }, >> Proto => 'tcp', >> Listen => 1, >> ReuseAddr => 1, >> ) or die $!; >> >> >> my $pid = fork; >> if(!defined($pid)){ >> say "FATAL! Sem recursos para o fork! Abortando!"; >> exit 0; >> } >> elsif($pid == 0){ >> my $newconn = &get_conn(); >> while(1){ >> #uma 'pá' de coisa aqui no child... >> sleep 60; >> } >> exit(1); >> } >> else { >> my $r = undef; >> while(1){ >> say "I'm working!"; >> if( $r = $usock->accept ){ >> &process_commands($r, \$usock); >> } >> else { >> $logerr->write('error','Problemas com o socket! >> Abortando!' . $!); >> exit(0); >> } >> sleep 1; >> } >> # $usock->close; >> close $out; >> >> waitpid($pid,0); >> } >> >> >> >> sub process_commands { >> my $sh = shift; >> my $rsock = shift; >> my $res = 0; >> while(<$sh>){ >> #tratando o que vem do client >> my $out = $_ || 'none'; >> $out =~ s/^(\ |\t)+//; >> my @params = split /\ +/, $out; >> my ($command,$parameter) = ( $params[0],$params[1] ); >> #separando algumas informações >> my %client_auth_data = ( host => undef, >> user => undef, >> password => undef, >> port => undef, >> ); >> >> #Implementar a camada de autenticação aqui. >> >> given($command){ >> when( 'stopsafe' ){ >> say 'Executando o stopsafe'; >> if(!&pause_MTAs()){ >> #enviar mensagem de erro via socket >> } >> else { >> #enviar mensagem de ok para o socket... >> } >> >> $res = 1; >> } >> #mais uma pancada de comandos aqui... >> default { >> my $msg = "Comando inválido! '$command $parameter' "; >> } >> } >> } >> return $res; >> } >> >> >> >> </code> >> >> >> Resumo: Eu tenho um processo que fica executando várias outras coisas, e >> um outro só para ficar escutando comando vindo do socket do lado do CLIENT! >> O que eu quero fazer, imagino eu, seria gravar alguma coisa no socket de >> dentro dessa função 'process_commands'. E de alguma forma ler isso do >> client. >> >> >> >> CLIENT >> >> <code> >> use strict; >> use warnings; >> use IO::Socket::INET; >> . >> . >> . >> >> my ($bind, $port ) = @_; >> my $sock = IO::Socket::INET->new ( >> PeerAddr => $bind, >> PeerPort => $port, >> Proto => 'tcp', >> Blocking => 0, >> ReuseAddr => 1, >> ) or die $!; >> >> $sock->send('chave1 valor1 chave2 valor2'); >> >> while(<$sock>){ >> #Teoricamente deveria ter alguma coisa no socket, mas nao rola... >> } >> >> $sock->close(); >> >> >> </code> >> >> >> Perguntas: >> >> >> - Como gravar no socket do lado do server, de modo que isso seja legível >> do lado do client? >> > > Uma das maneiras é assim : > > <code> > > #!/usr/bin/env perl > use strict; > use IO::Socket::INET; > > my $quit = 0; > > $SIG{INT} = sub { $quit++ }; > > my $listen_socket = IO::Socket::INET->new(LocalPort => 2121, > Listen => 2, > Proto => 'tcp', > Reuse => 1,) or die "$!"; > > while ( !$quit ) { > next unless my $connection = $listen_socket->accept; > > defined ( my $child = fork() ) or die "Can't fork: $!"; > > if ( $child == 0 ) { > $listen_socket->close; > do_something($connection); > exit 0; > } > > $connection->close; > > } > > sub do_something { > my $socket = shift; > > $socket->autoflush(1); > $socket->print("Entre com os numeros para calculo:\n"); > > while ( 1 ) { > my $input = $socket->getline(); > exit 0 if $input =~ /quit/i; > $socket->print($input); > } > > } > > <code> > > O código acima é um echo server muito simples, que ilustra bem uma > comunicação bi-direcional. Não sei onde você está utilizando este código, > mas eu recomendo muito cuidado. Existem vários problemas com código deste > tipo (I/O Blocking, por exemplo) e uma enorme quantidade de coisas que podem > ocorrer de errado. > > Tenho um livro (Networking Programming with Perl) de 700 páginas só falando > de tudo que pode dar errado num código deste tipo e todas (ou quase) > variações de servidores escrito em Perl (tcp, udp, I/O Blocking, I/O > Nonblocking, forked, threaded). Utilizar print/getline, write/read, > syswrite/sysread é apenas o começo das perguntas de arquitetura que temos > que responder para um servidor. > > Se for possível, eu recomendo fortemente que você utilize um framework para > fazer isto, tipo o POE (http://poe.perl.org/?POE_Cookbook/TCP_Servers tem > um exemplo do mesmo código que eu escrevi). Se não for possível, eu > recomendo você dar uma olhada no livro que eu disse (posso emprestar se for > o caso). Temos também o Mojolicious com os websocket (estou começando a ver > isto), pode ser uma boa alternativa. > > - Preciso de protocolo específico para fazer isso ? >> > > Uma conversa bi-direcional, você precisa definir os comandos que um vai > aceitar do outro. Você terá que criar algum protocolo de qualquer maneira, > uma linguagem que seja compreendida pelo servidor e cliente, qual como o > HTTP, FTP ou SMTP. Na transferência de arquivo, recomendo fortemente no > formato JSON. Aliais, este teu sistema não seria candidato para ser um > webapp com RESTfull web services implementado em Catalyst ou Mojolicious ? > Neste ambiente O URI é a função que recebe/retorna em JSON, sem view em html > ! > > >> - Eu vi algumas pessoas usando udp ao invés de tcp alegando aumento de >> performance, mas abrindo mão de vários quesitos de segurança dentre outros >> problemas. Confirma? >> >> > Sim, o UDP é mais 'leve' do que o 'tcp'. Mas isto significa que você terá > que tratar tudo relacionado a transferência de dados (ordem dos pacotes, > perda dos pacotes, etc). Uma recomendação, a menos que você saiba muito bem > o que está fazendo, e que o consumo de rede seja justificado, não utilize o > UDP, o overhead para o programador não vale a pena. O HTTP utiliza TCP e > ninguém pensou em mudar isto, não siga os líderes :D .... > digo, siga os líderes .... > > >> Cheers! >> >> >> -- >> André Garcia Carneiro >> Analista/Desenvolvedor Perl >> (11)82907780 >> >> =begin disclaimer >> Sao Paulo Perl Mongers: http://sao-paulo.pm.org/ >> SaoPaulo-pm mailing list: SaoPaulo-pm@pm.org >> L<http://mail.pm.org/mailman/listinfo/saopaulo-pm> >> =end disclaimer >> >> > > > -- > "o animal satisfeito dorme". - Guimarães Rosa > -- "o animal satisfeito dorme". - Guimarães Rosa
=begin disclaimer Sao Paulo Perl Mongers: http://sao-paulo.pm.org/ SaoPaulo-pm mailing list: SaoPaulo-pm@pm.org L<http://mail.pm.org/mailman/listinfo/saopaulo-pm> =end disclaimer