[SP-pm] Socket - algumas questões:
Solli Honorio
shonorio at gmail.com
Tue May 3 12:01:11 PDT 2011
Em 3 de maio de 2011 15:59, Solli Honorio <shonorio em gmail.com> escreveu:
>
>
> 2011/5/3 Andre Carneiro <andregarciacarneiro em 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 em 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
-------------- Pr?xima Parte ----------
Um anexo em HTML foi limpo...
URL: <http://mail.pm.org/pipermail/saopaulo-pm/attachments/20110503/6381b782/attachment-0001.html>
More information about the SaoPaulo-pm
mailing list