<br><div class="gmail_quote">Em 3 de maio de 2011 15:59, Solli Honorio <span dir="ltr"><<a href="mailto:shonorio@gmail.com">shonorio@gmail.com</a>></span> escreveu:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">

<br><br><div class="gmail_quote"><div class="im">2011/5/3 Andre Carneiro <span dir="ltr"><<a href="mailto:andregarciacarneiro@gmail.com" target="_blank">andregarciacarneiro@gmail.com</a>></span><br></div><div><div>
</div>
<div class="h5"><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
Salve Monges!<div><br></div><div><br></div><div>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:</div>



<div><br></div><div>- O 'socket' do lado do 'client' escreve coisas no socket </div><div>- O 'socket' do lado do server lê coisas do Socket;</div><div><br></div><div>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:</div>



<div><br></div><div><br></div><div>SERVER: </div><div><br></div><div><code></div><div>use strict;</div><div>use warnings;</div><div>use IO::Socket::INET</div><div>use Daemon::Generic;</div><div>use feature qw/ say switch /;</div>



<div>.</div><div>.</div><div>.</div><div>#configuração</div><div>.</div><div>.</div><div>.</div><div><div>    my $usock = IO::Socket::INET->new ( </div><div>                            Type<span style="white-space: pre-wrap;">               </span>=> SOCK_STREAM ,</div>



<div>                            LocalAddr<span style="white-space: pre-wrap;">   </span>=> $config_socket->{ SocketBind },</div><div>                            LocalPort<span style="white-space: pre-wrap;">  </span>=> $config_socket->{ SocketPort },</div>



<div>                            Proto<span style="white-space: pre-wrap;">               </span>=> 'tcp',</div><div>                            Listen<span style="white-space: pre-wrap;">         </span>=> 1,</div>
<div>                            ReuseAddr<span style="white-space: pre-wrap;">   </span>=> 1,</div><div><span style="white-space: pre-wrap;">       </span>                ) or die $!;</div></div>
<div><br></div><div><br></div><div>  my $pid = fork;</div><div>      if(!defined($pid)){</div><div>        say "FATAL! Sem recursos para o fork! Abortando!";</div><div>        exit 0;</div><div>    }</div><div>


    elsif($pid == 0){</div>
<div>        my $newconn = &get_conn(); </div><div>        while(1){</div><div>            #uma 'pá' de coisa aqui no child...</div><div>            sleep 60;</div><div>        }</div><div>        exit(1);</div>



<div>    }</div><div>    else {</div><div>        my $r = undef;</div><div>        while(1){</div><div>            say "I'm working!";</div><div>            if( $r = $usock->accept ){</div><div>                &process_commands($r, \$usock);</div>



<div>            }</div><div>            else {</div><div>                $logerr->write('error','Problemas com o socket! Abortando!' . $!);</div><div>                exit(0);</div><div>            }</div>



<div>            sleep 1;</div><div>        }</div><div>#        $usock->close;</div><div>        close $out;</div><div><br></div><div>        waitpid($pid,0);</div><div>    }</div><div><br></div><div><br></div><div><br>



</div><div><div>sub process_commands {</div><div>    my $sh = shift;</div><div>    my $rsock = shift;</div><div>    my $res = 0;</div><div>    while(<$sh>){</div><div>        #tratando o que vem do client</div><div>



        my $out = $_ || 'none';</div><div>        $out =~ s/^(\ |\t)+//;</div><div>        my @params = split /\ +/, $out;</div><div>        my ($command,$parameter) = ( $params[0],$params[1] );</div><div>        #separando algumas informações</div>



<div>        my %client_auth_data = (    host     => undef,</div><div>                                    user     => undef,</div><div>                                    password => undef,</div><div>                                    port     => undef,</div>



<div>                        );</div><div><br></div><div>        #Implementar a camada de autenticação aqui.</div><div><br></div><div>        given($command){</div><div>            when( 'stopsafe' ){</div><div>                say 'Executando o stopsafe';</div>



<div>                if(!&pause_MTAs()){</div><div>                         #enviar mensagem de erro via socket </div><div>                }</div><div>                else {</div><div>                         #enviar mensagem de ok para o socket...</div>



<div>                } </div><div><br></div><div>                $res = 1;</div><div>            }</div><div>            #mais uma pancada de comandos aqui...</div><div>            default {</div><div>                my $msg = "Comando inválido! '$command $parameter' ";</div>



<div>            }</div><div>        }</div><div>    }</div><div>    return $res;</div><div>}</div></div><div><br></div><div><br></div><div><br></div><div></code></div><div><br></div><div><br></div><div>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.</div>



<div><br></div><div><br></div><div><br></div><div>CLIENT</div><div><br></div><div><code></div><div>    use strict;</div><div>    use warnings;</div><div>    use IO::Socket::INET;</div><div>    .</div><div>    .</div>



<div>    .</div><div><br></div><div><div>    my ($bind, $port ) = @_;</div><div>    my $sock = IO::Socket::INET->new ( </div><div>                                PeerAddr<span style="white-space: pre-wrap;">    </span>=> $bind,</div>



<div>                                PeerPort<span style="white-space: pre-wrap;">        </span>=> $port,</div><div>                                Proto<span style="white-space: pre-wrap;">              </span>=> 'tcp',</div>



<div>                                Blocking    => 0,</div><div>                                ReuseAddr   => 1,</div><div>                        ) or die $!;</div><div> </div><div>    $sock->send('chave1 valor1 chave2 valor2');</div>



<div><br></div><div>    while(<$sock>){</div><div><span style="white-space: pre-wrap;">       </span>#Teoricamente deveria ter alguma coisa no socket, mas nao rola...</div><div>    }</div><div><br></div><div>
    $sock->close();</div></div><div><br></div><div><br></div><div></code></div><div><br></div><div><br></div><div>Perguntas:</div><div><br></div><div><br></div><div>- Como gravar no socket do lado do server, de modo que isso seja legível do lado do client?</div>


</blockquote></div></div><div><br><span style="font-family: courier new,monospace;">Uma das maneiras é assim : </span><br><br><code><br><br><span style="font-family: courier new,monospace;">#!/usr/bin/env perl  </span><br style="font-family: courier new,monospace;">


<span style="font-family: courier new,monospace;">use strict;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">use IO::Socket::INET;</span><br style="font-family: courier new,monospace;">


<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">my $quit = 0;</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">$SIG{INT} = sub { $quit++ };</span><br style="font-family: courier new,monospace;">


<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">my $listen_socket = IO::Socket::INET->new(LocalPort => 2121,</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">                                        Listen    => 2,</span><br style="font-family: courier new,monospace;">


<span style="font-family: courier new,monospace;">                                        Proto     => 'tcp',</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">                                        Reuse     => 1,) or die "$!";</span><br style="font-family: courier new,monospace;">


<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">while ( !$quit ) {</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">  next unless my $connection = $listen_socket->accept;   </span><br style="font-family: courier new,monospace;">


<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">  defined ( my $child = fork() ) or die "Can't fork: $!";</span><br style="font-family: courier new,monospace;">


<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">  if ( $child == 0 ) {</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    $listen_socket->close;</span><br style="font-family: courier new,monospace;">


<span style="font-family: courier new,monospace;">    do_something($connection);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    exit 0;</span><br style="font-family: courier new,monospace;">


<span style="font-family: courier new,monospace;">  }</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">  $connection->close;</span><br style="font-family: courier new,monospace;">


<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">}                    </span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">


<span style="font-family: courier new,monospace;">sub do_something {</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">  my $socket = shift;   </span><br style="font-family: courier new,monospace;">


<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">  $socket->autoflush(1);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">  $socket->print("Entre com os numeros para calculo:\n");</span><br style="font-family: courier new,monospace;">


<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">  while ( 1 ) {</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    my $input = $socket->getline();</span><br style="font-family: courier new,monospace;">


<span style="font-family: courier new,monospace;">    exit 0 if $input =~ /quit/i;   </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    $socket->print($input);</span><br style="font-family: courier new,monospace;">


<span style="font-family: courier new,monospace;">  }</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">   </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">}  </span><br style="font-family: courier new,monospace;">


<br style="font-family: courier new,monospace;"><code><br> <br><span style="font-family: courier new,monospace;">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. <br>


<br>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.</span><br style="font-family: courier new,monospace;">


<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">Se for possível, eu recomendo fortemente que você utilize um framework para fazer isto, tipo o POE (<a href="http://poe.perl.org/?POE_Cookbook/TCP_Servers" target="_blank">http://poe.perl.org/?POE_Cookbook/TCP_Servers</a> 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.</span><br>


<br></div><div class="im"><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div>- Preciso de protocolo específico para fazer isso ?</div></blockquote></div><div><br><span style="font-family: courier new,monospace;">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 !</span><br>


 </div><div class="im"><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div>- 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?</div>



<div><br></div></blockquote></div><div><br><span style="font-family: courier new,monospace;">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 ....  </span><br>

</div></div></blockquote><div><br>digo, siga os líderes ....<br> </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div class="gmail_quote">

<div>
<br></div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div class="im"><div></div><div><br></div><div>Cheers!</div><div><br></div><font color="#888888"><div>


<br>-- <br>André Garcia Carneiro<br>Analista/Desenvolvedor Perl<br>
(11)82907780<br>
</div>
</font><br></div><div class="im">=begin disclaimer<br>
   Sao Paulo Perl Mongers: <a href="http://sao-paulo.pm.org/" target="_blank">http://sao-paulo.pm.org/</a><br>
 SaoPaulo-pm mailing list: <a href="mailto:SaoPaulo-pm@pm.org" target="_blank">SaoPaulo-pm@pm.org</a><br>
 L<<a href="http://mail.pm.org/mailman/listinfo/saopaulo-pm" target="_blank">http://mail.pm.org/mailman/listinfo/saopaulo-pm</a>><br>
=end disclaimer<br>
<br></div></blockquote></div><font color="#888888"><br><br clear="all"><br>-- <br>"o animal satisfeito dorme". - Guimarães Rosa<br>
</font></blockquote></div><br><br clear="all"><br>-- <br>"o animal satisfeito dorme". - Guimarães Rosa<br>