Quizás pasa lo que dice Jenda: que el servidor no sabe cuándo ha terminado de recibirlo todo...
Si yo creo un servidor que esté preparado para recibir bloques de 62 bytes (el tamaño del array @a) entonces sí que funciona:
servidor:
Using perl Syntax Highlighting
#!/usr/bin/perl -w
use strict
;
use IO
::Socket;
my $sock = new IO
::Socket::INET(
LocalHost
=> 'localhost',
LocalPort
=> 7890,
Proto
=> 'tcp',
Listen
=> SOMAXCONN
,
Reuse
=> 1
);
$sock or die "no socket :$!";
STDOUT
->autoflush(1
);
my($new_sock, $buf);
while ($new_sock = $sock->accept()) {
read $new_sock, $buf, 62;
print ord($_)," " foreach split //, $buf;
print "\n";
print $new_sock "ENVIADO!\n";
close $new_sock;
}Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
cliente:
Using perl Syntax Highlighting
#!/usr/bin/perl -w
use strict
;
use IO
::Socket;
my $sock = new IO
::Socket::INET(
PeerAddr
=> 'localhost',
PeerPort
=> 7890,
Proto
=> 'tcp');
$sock or die "no socket :$!";
my @a = ( 1
, 59
, 160
, 1
, 1
, 1
, 160
, 1
, 1
, 20
, 49
, 46
, 50
, 98
, 44
, 77
,
111
, 118
, 105
, 115
, 116
, 97
, 114
, 44
, 105
, 110
, 116
, 101
, 114
, 110
, 101
, 116
,
46
, 103
, 112
, 114
, 115
, 46
, 117
, 110
, 105
, 102
, 111
, 110
, 46
, 99
, 111
, 109
,
46
, 97
, 114
, 44
, 119
, 97
, 112
, 44
, 119
, 97
, 112
, 0
, 34
, 3
);
print "Enviando ", scalar @a, " elementos\n";
foreach (@a) {
print $sock chr($_);
}
print scalar <$sock>; # Respuesta del servidor
close $sock;Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
Arrancamos el servidor en una terminal, y el cliente en otra. En la del servidor aparecen la ristra de bytes y queda esperando para la siguiente. En la del cliente, aparece el indicativo de que sí han sido enviados y recibidos por el servidor. Pero esto lo podemos hacer porque el servidor sabe exáctamente que tiene que leer solo 62 bytes antes de continuar con el programa. No está contemplado otro caso, como por ejemplo que la longitud sea distinta o que la comunicación se corte a la mitad.
Viendo la lista de bytes, se nota que hay muchas minúsculas, así que se trata de un texto, junto con otros valores en binario. De todos los valores, el que me llama la atención es el segundo: está indicando la longitud de los datos que le siguen.
Supongamos que el protocolo es ese: el bloque de datos comienza con un 1 y le sigue un byte que indica lo que le sigue. El servidor sabe entonces cuánta información debe leer.
Con este nuevo servidor:
Using perl Syntax Highlighting
#!/usr/bin/perl -w
use strict
;
use IO
::Socket;
my $sock = new IO
::Socket::INET(
LocalHost
=> 'localhost',
LocalPort
=> 7890,
Proto
=> 'tcp',
Listen
=> SOMAXCONN
,
Reuse
=> 1
);
$sock or die "no socket :$!";
STDOUT
->autoflush(1
);
my($new_sock, $buf);
while ($new_sock = $sock->accept()) {
$buf = getc $new_sock; # Leemos el primer byte
if ( $buf eq "\1" ) {
print "Recibido inicio de paquete\n";
my $longitud = 1
+ ord getc $new_sock; # Esperar la llegada de la longitud
print "Recibiendo $longitud bytes\n";
read $new_sock, $buf, $longitud; # Leemos esa cantidad
my ($h1,$h2,$texto,$crc) # Desempaquetado
= unpack("H8 H8 Z* H4", $buf);
print "$h1,$h2\n";
print "Texto:$texto.\n";
print "$crc\n";
print $new_sock "ENVIADO!\n";
}
}Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
y ahora el nuevo cliente:
Using perl Syntax Highlighting
#!/usr/bin/perl -w
use strict
;
use IO
::Socket;
my $sock = new IO
::Socket::INET(
PeerAddr
=> 'localhost',
PeerPort
=> 7890,
Proto
=> 'tcp');
$sock or die "no socket :$!";
my $texto = '1.2b,Movistar,internet.gprs.unifon.com.ar,wap,wap';
print $sock "\1"; # Cabecera
print $sock chr(length($texto)+1
+8
+2
-1
); # uno menos
print $sock chr $_ foreach ( 0xa0
, 0x01
, 0x01
, 0x01
, 0xa0
, 0x01
, 0x01
, 0x14
); # 8
print $sock "$texto\0"; # 50
print $sock chr 0x22
, chr 0x03
; # 2
print scalar <$sock>; # Respuesta del servidor
close $sock;Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
obtenemos la misma respuesta, pero ahora el servidor ya está preparado para recibir otros textos con distinta longitud, y el cliente está modificado para ser fácil enviar otros textos.
Notar la facilidad de unpack en el servidor. Queda como ejercicio hacer lo mismo en la parte del cliente, para dejarlo incluso más sencillo.
(Movistar, ¿eh?
)
Imprescindible ver la página de
Linux Journal sobre Networking.