Yaih Carneiro!<div>Que eu me lembre, accept() precisa retornar 2 sockets: accept(Client, Server). Você pode, sim, ler e gravar no socket do client, mas no server devem ser separados.</div><div>Um aviso: seu código terá sérios problemas de escalabilidade por causa do fork(). E, como vc já deve prever, eu recomendaria o fabuloso AnyEvent :D</div>

<div>Veja um servidor HTTPD toscão que aguenta 100 conexões simultâneas sem apelar p/load descomunal:</div><div><br></div><div><meta http-equiv="content-type" content="text/html; charset=utf-8"><a href="https://gist.github.com/781246">https://gist.github.com/781246</a><br clear="all">

<br>ABS()<br><br>
<br><br><div class="gmail_quote">2011/5/3 Andre Carneiro <span dir="ltr"><<a href="mailto:andregarciacarneiro@gmail.com">andregarciacarneiro@gmail.com</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;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>


<div>- Preciso de protocolo específico para fazer isso ?</div><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><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div>Cheers!</div><div><br></div><font color="#888888"><div><br></div><div><br clear="all"><br>-- <br>André Garcia Carneiro<br>

Analista/Desenvolvedor Perl<br>
(11)82907780<br>
</div>
</font><br>=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">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></blockquote></div><br></div>