<HTML><HEAD></HEAD>
<BODY dir=ltr>
<DIV dir=ltr>
<DIV style="FONT-FAMILY: 'Calibri'; COLOR: #000000; FONT-SIZE: 12pt">
<DIV>Tiago,</DIV>
<DIV> </DIV>
<DIV></DIV>
<DIV>mesmo sabendo usar um framework tipo Net::Server (p.exe), </DIV>
<DIV>vai ser sua responsabilidade tratar a conversa com o cliente de forma 
robusta, sem impactos negativos no seu ‘server’.</DIV>
<DIV> </DIV>
<DIV></DIV>
<DIV>estando no contexto de um processo filho do server, vai ter que ler o 
socket até receber a <U>estrutura completa</U> da msg estipulada:</DIV>
<DIV> </DIV>
<DIV></DIV>
<DIV>- seja por tamanho da msg (meu caso no exemplo do codigo abaixo)</DIV>
<DIV>- seja por CRLF (seu caso)</DIV>
<DIV>- seja por outra estrutura qqe</DIV>
<DIV> </DIV>
<DIV></DIV>
<DIV>Tendo recebido a msg completa, passa-se então para o parser 
validá-la.</DIV>
<DIV> </DIV>
<DIV></DIV>
<DIV>O seu problema, pelo que entendi, é tratar de forma robusta a conversa com 
o cliente, independente do que ele faça ou não faça – sem afetar o funcionamento 
do server.</DIV>
<DIV> </DIV>
<DIV></DIV>
<DIV>Leia o trecho de codigo abaixo assumindo que:</DIV>
<DIV> </DIV>
<DIV></DIV>
<DIV>- o processo que chama a sub <EM>_read_socket</EM> foi forkado pelo 
server</DIV>
<DIV>- o socket acceptado na conversa com o cliente esta mapeado no STDIN</DIV>
<DIV>- importante, nesse caso, _read_socket le o socket ate atingir $sz bytes de 
conversa <EM>=> mude a sub para ler enquanto nao encontra o seu 
CRLF</EM></DIV>
<DIV>- $$pin vai conter a msg de $sz bytes</DIV>
<DIV>- em caso de timeout na conversa, devolve erro</DIV>
<DIV></DIV>
<DIV> </DIV>
<DIV>Nao tem probl ficarmos blocados nessa sub esperando a msg completa dado que 
somos um filho forkado do server e estamos suportados pelo timeout na 
conversa.</DIV>
<DIV> </DIV>
<DIV>Assuma tb que o server nao starta mais do que N filhos e os controla 
bonitinho (cria e mata se for o caso). Net::Server faz isso por vc.</DIV>
<DIV> </DIV>
<DIV></DIV>
<DIV>No nosso caso, refizemos o server para ser mais leve e acabamos nao usando 
o Net::Server.</DIV>
<DIV></DIV>
<DIV> </DIV>
<DIV>Alguem, acima, vai tratar e parsear a msg em $$pin, depois de ter recebido 
a msg completa.</DIV>
<DIV></DIV>
<DIV> </DIV>
<DIV>Espero que ajude, pontualmente, na sua questão principal que é ler o socket 
de forma segura, sem impactos negativos no processo.</DIV>
<DIV></DIV>
<DIV><EM></EM> </DIV>
<DIV><EM>sub _read_socket {</EM></DIV>
<DIV><EM>    my $self = shift;</EM></DIV>
<DIV><EM>    my $pin  = shift;</EM></DIV>
<DIV><EM>    my $sz   = shift;</EM></DIV>
<DIV><EM></EM> </DIV>
<DIV><EM>    # tratamento de timeout por select e nao por 
alarm!</EM></DIV>
<DIV><EM>    my $idle_max = $self->{TIMEOUT_SOCKET} || 
10;</EM></DIV>
<DIV><EM>    my $idle     = 0;</EM></DIV>
<DIV><EM>    my $mask;</EM></DIV>
<DIV><EM>    vec($mask, fileno(STDIN), 1) = 1;</EM></DIV>
<DIV><EM></EM> </DIV>
<DIV><EM>    my $nr;</EM></DIV>
<DIV><EM>    my $buf;</EM></DIV>
<DIV><EM>    my $len = 0;</EM></DIV>
<DIV><EM>    my $off = 0;</EM></DIV>
<DIV><EM>    while (1) {</EM></DIV>
<DIV><EM></EM> </DIV>
<DIV><EM>        if ($idle > $idle_max) 
{</EM></DIV>
<DIV><EM>            
return(0,3,"Socket read timeout ($idle_max segs). Esperados $sz bytes, 
recebido(s) $len");</EM></DIV>
<DIV><EM>        }</EM></DIV>
<DIV><EM>        my $rmask = 
undef;</EM></DIV>
<DIV><EM>        my $sel   = 
select($rmask=$mask, undef, undef, 1); # 1seg</EM></DIV>
<DIV><EM>        if (!$sel) { $idle++; next; 
};</EM></DIV>
<DIV><EM>        if(vec($rmask, 
fileno(STDIN), 1)) {</EM></DIV>
<DIV><EM></EM> </DIV>
<DIV><EM>            eval 
{ $nr = sysread(STDIN, $buf, $sz-$len, $off); };</EM></DIV>
<DIV><EM>            if 
($@) {</EM></DIV>
<DIV><EM>                
return(0,3,"Erro ao ler socket: $@: $buf");</EM></DIV>
<DIV><EM>            
}</EM></DIV>
<DIV><EM>            if 
($!) {</EM></DIV>
<DIV><EM>                
return(0,3,"Erro ao ler socket: $!: $buf");</EM></DIV>
<DIV><EM>            
}</EM></DIV>
<DIV><EM>            
unless ($nr) {</EM></DIV>
<DIV><EM>                
return(0,3,"Erro ao ler socket: EOF");</EM></DIV>
<DIV><EM>            
}</EM></DIV>
<DIV><EM>            
$self->_info("SOCKET IN $nr = [". substr($buf, $off, $nr) . ']'); # if 
($self->{DEBUG} > 2);</EM></DIV>
<DIV><EM>            $off 
+= $nr;</EM></DIV>
<DIV><EM>            $len 
+= $nr;</EM></DIV>
<DIV><EM>            last 
if ($len >= $sz);</EM></DIV>
<DIV><EM>        }</EM></DIV>
<DIV><EM>    }</EM></DIV>
<DIV><EM></EM> </DIV>
<DIV><EM>    $$pin = $buf;</EM></DIV>
<DIV><EM>    return(1,0,'');</EM></DIV>
<DIV><EM>}</EM></DIV>
<DIV> </DIV>
<DIV> </DIV>
<DIV style="FONT-FAMILY: 'Calibri'; COLOR: #000000; FONT-SIZE: 12pt"><!-- saved from url=(0022)http://internet.e-mail -->
<TABLE style="COLOR: #000000">
  <TBODY>
  <TR>
    <TD vAlign=bottom align=left><IMG alt="IBIZ Tecnologia" 
      src="http://www.ibiz.com.br/Imagens/logoibiz_sombra_NEW.gif"> </TD>
    <TD> </TD>
    <TD> </TD>
    <TD vAlign=middle align=left><FONT color=#666666 size=2 
      face="Verdana, Helvetica, Arial, sans-serif"><B>Ulisses Gomes</B><BR><FONT 
      size=1>Tecnologia da Informação<BR><BR>IBIZ Tecnologia<BR>+55 11 5579-3178 
      r. 226<BR><U>ulisses@ibiz.com.br</U><BR><A 
      href="http://www.ibiz.com.br">www.ibiz.com.br</A></FONT></FONT> 
  </TD></TR></TBODY></TABLE><BR><IMG alt="pense verde!" align=left 
src="http://www.ibiz.com.br/Imagens/pense_verde.gif"> <BR>
<DIV align=justify><FONT color=#aaaaaa size=1 face="Arial, sans-serif">
<P><BR><BR>Esta mensagem de correio eletrônico e seus documentos anexos estão 
dirigidos EXCLUSIVAMENTE aos destinatários especificados. A informação contida 
pode ser CONFIDENCIAL e/ou estar LEGALMENTE PROTEGIDA e não necessariamente 
reflete a opinião da IBIZ. Se você receber esta mensagem por ENGANO, por favor, 
comunique imediatamente ao remetente e ELIMINE-A já que você NÃO ESTÁ AUTORIZADO 
ao uso, revelação, distribuição, impressão ou cópia de toda ou alguma parte da 
informação contida. Obrigado. </P></FONT></DIV></DIV>
<DIV 
style="FONT-STYLE: normal; DISPLAY: inline; FONT-FAMILY: 'Calibri'; COLOR: #000000; FONT-SIZE: small; FONT-WEIGHT: normal; TEXT-DECORATION: none">
<DIV style="FONT: 10pt tahoma">
<DIV> </DIV>
<DIV style="BACKGROUND: #f5f5f5">
<DIV style="font-color: black"><B>From:</B> <A title=tiago.peczenyj@gmail.com 
href="mailto:tiago.peczenyj@gmail.com">Tiago Peczenyj</A> </DIV>
<DIV><B>Sent:</B> Sunday, November 25, 2012 1:47 PM</DIV>
<DIV><B>To:</B> <A title=saopaulo-pm@mail.pm.org 
href="mailto:saopaulo-pm@mail.pm.org">saopaulo-pm@mail.pm.org</A> </DIV>
<DIV><B>Subject:</B> Re: [SP-pm] duvida sockets e select</DIV></DIV></DIV>
<DIV> </DIV></DIV>
<DIV 
style="FONT-STYLE: normal; DISPLAY: inline; FONT-FAMILY: 'Calibri'; COLOR: #000000; FONT-SIZE: small; FONT-WEIGHT: normal; TEXT-DECORATION: none">uma 
parte do meu protocolo é 
<DIV> </DIV>
<DIV>timestamp<SEPARADOR>tipo<SEPARADOR>etc..CRLF</DIV>
<DIV> </DIV>
<DIV>sendo meu separador algo arbitrario, uma virgula por exemplo. é uma string 
utf-8</DIV>
<DIV> </DIV>
<DIV>eu criei um buffer para entra entrada e vou acumulando até encontrar uma 
linha e assim processar</DIV>
<DIV> </DIV>
<DIV>meu problema era que como eu tenho que rotear estes eventos para outros 
clientes baseados em regras internas, tenho que usar I/O nonblocking para não 
ficar travado se um cliente não esta lendo/escrevendo (meu cliente só se 
identifica), ou se a fonte de eventos não esta escrevendo. agora eu resolvi isso 
de forma razoavel mas tudo esta sobrecarregado em um processo. se eu 
quiser  usar outros processos ou mesmo outras maquinas fisicas eu tenho que 
pensar mais um pouco pois eu tenho um estado interno (baseado nos eventos) que 
preciso replicar e aquela coisa toda que a gente resolve usando banco de dados, 
filas de mensagens, load balance, sistema de arquivos, etc. como é prova de 
conceito não quero sobracarregar com muita coisa que agora eu não 
preciso.<BR><BR>
<DIV class=gmail_quote>2012/11/25 Thiago Rondon <SPAN dir=ltr><<A 
href="mailto:thiago@aware.com.br" 
target=_blank>thiago@aware.com.br</A>></SPAN><BR>
<BLOCKQUOTE 
style="BORDER-LEFT: #ccc 1px solid; MARGIN: 0px 0px 0px 0.8ex; PADDING-LEFT: 1ex" 
class=gmail_quote><BR>Tiago,<BR><BR>Uma pergunta: Qual o padrão do teu 
  protocolo ? Me parece que o maior problema aqui é a falta de um padrão para 
  disposição e processamento.<BR><BR>Basicamente, a pergunta: É orientado a 
  linhas ou é a blocos ? Deve ser respondida tanto do lado de disposição, como 
  de processamento. E ela deve ser bem "clara" e "suave" para ambas na minha 
  opinião.<BR><BR>Me parece que teu problema, exige algo orientada a blocos, 
  algo como alguns protocolos já funcionam assim.<BR><BR>Mas, voltando ao 
  problema. Se for a linha, para solucionar o seu problema, você provavelmente 
  vai ter que depender de um "histórico" comum, como por exemplo criar uma pilha 
  de processamento, e manter o tamanho desta pilha em um determinado tamanho, o 
  que também deve ser "especificado" no protocolo, qual o tamanho que ela pode 
  ter, e quais características ela deve ter. Como por exemplo, o que defini que 
  uma linha vai para um buffer, ou não, e por aí vai.<BR><BR>Se for por blocos, 
  por exemplo separado por duas linhas, fica mais simples, pois você pode ter 
  algo como:<BR><BR>$buffer =~ s/^(.+)(?:\015\012\015\012)//sox<BR><BR>O uso do 
  POE é bem interessante neste caso, pois ele oferece o método 
  "anyevent_read_type" para definir o formato do seu protocolo na sua classe, e 
  "configurando" ela de forma que corresponde ao teu protocolo, todo o resto 
  fica bem mais simples de se manusear e sem muitos efeitos 
  colaterais.<BR><BR>abs!<BR>-Thiago Rondon<BR>
  <DIV class=im><BR><BR>On Saturday, November 24, 2012 at 7:52 PM, Tiago 
  Peczenyj wrote:<BR><BR>> Ok<BR>><BR>> Recebi a dica de usar sysread e 
  "funciona"<BR>><BR>> entretanto o meu problema é: eu tenho um protocolo 
  orientado a linhas, cada linha é um "evento" que eu preciso processar. posso 
  pegar uma linha pela metade e eu teria que guardar para "emendar" no proximo 
  loop.<BR>><BR>> pensei em algo como<BR>><BR>> while ($buf =~ 
  s/^(.*)\n//) { process_message("$1"); }<BR>> mas como eu faço na 
  situação<BR>><BR>> envio<BR>><BR>> linha1<BR>> linha2<BR>> 
  linha3<BR>><BR>> e quando leio...<BR>><BR>> buffer => 
  "linha1\r\nlin";<BR>><BR>> eu preciso guardar o "lin" pra proxima fase. 
  tem alguma forma menos obscura de faze-lo?<BR>><BR></DIV>> 2012/11/24 
  Tiago Peczenyj <<A 
  href="mailto:tiago.peczenyj@gmail.com">tiago.peczenyj@gmail.com</A> (mailto:<A 
  href="mailto:tiago.peczenyj@gmail.com">tiago.peczenyj@gmail.com</A>)><BR>
  <DIV class=im>> > Ola Galera<BR>> ><BR>> > Eu tenho algo 
  mais ou menos assim<BR>> ><BR>> > <A 
  href="https://gist.github.com/4141422" 
  target=_blank>https://gist.github.com/4141422</A><BR>> ><BR>> > O 
  que acontece é que, se eu fizer<BR>> ><BR>> > bash$ (echo "xxx" 
  ;sleep 30 ; echo "yyy") | nc localhost 9090<BR>> ><BR>> > ta de 
  boa, o xxx e o yyy são impressos em momentos distintos mas<BR>> 
  ><BR>> > bash$ (echo -n "xxx" ;sleep 30 ; echo "yyy") | nc localhost 
  9090<BR>> ><BR>> > O server TRAVA enquanto<BR>> ><BR>> 
  > Agora o que acontece: eu tenho que escutar em outra porta (otimi o codigo 
  mas basicamente eu inicio outro IO::Socket::INET em outra porta e trato dentro 
  do main loop) outros clientes e fazer coisas divertidas com eles. com o server 
  travado eu não faço mais nada.<BR>> ><BR>> > achei q era o getline 
  mas substituindo por getc para ler caracter a caracter eu só consigo ler o 
  primeiro antes de travar.<BR>> ><BR>> > alguma ideia?<BR>> 
  ><BR>> > outra coisa, eu suportamente tenho que ler um protocolo 
  simples, uma linha com um padrão, como<BR>> ><BR>> > 
  a|b|c|d\r\n<BR>> ><BR>> > então o getline me é util, não achei 
  outra forma de brincar com um buffer sem ficar maluco. alias eu deveria 
  suportar utf-8 na entrada porem eu não vi diferença no binmode, tem algum 
  truque? estou esquecendo de algo? o common::sense ja faz algo por mim?<BR>> 
  ><BR>> > Obrigado<BR>> ><BR>> ><BR>> ><BR>> > 
  --<BR>> > Tiago B. Peczenyj<BR>> > Linux User #405772<BR>> 
  ><BR>> > <A href="http://pacman.blog.br" 
  target=_blank>http://pacman.blog.br</A><BR>><BR>><BR>><BR>> 
  --<BR>> Tiago B. Peczenyj<BR>> Linux User #405772<BR>><BR>> <A 
  href="http://pacman.blog.br" target=_blank>http://pacman.blog.br</A><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></DIV>> SaoPaulo-pm mailing 
  list: <A href="mailto:SaoPaulo-pm@pm.org">SaoPaulo-pm@pm.org</A> (mailto:<A 
  href="mailto:SaoPaulo-pm@pm.org">SaoPaulo-pm@pm.org</A>)<BR>
  <DIV class=HOEnZb>
  <DIV class=h5>> 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><BR><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></DIV></DIV></BLOCKQUOTE></DIV><BR><BR clear=all>
<DIV> </DIV>-- <BR>Tiago B. Peczenyj<BR>Linux User #405772<BR><BR><A 
href="http://pacman.blog.br">http://pacman.blog.br</A><BR></DIV>
<P>
<HR>
=begin disclaimer<BR>   Sao Paulo Perl Mongers: 
http://sao-paulo.pm.org/<BR>SaoPaulo-pm mailing list: 
SaoPaulo-pm@pm.org<BR>L<http://mail.pm.org/mailman/listinfo/saopaulo-pm><BR>=end 
disclaimer<BR></DIV></DIV></DIV></BODY></HTML>