- Вы не можете предполагать, что
recv
(или read
) вернет весь ответ.Вам нужно вызывать его повторно. - Вы не можете предполагать, что
recv
(или read
) будет просто ответом.Вам нужно ограничить размер чтения из буфера избытком. decode_json
возвращает ссылку (не список пар ключ-значение, которые вы можете присвоить хешу). - Выможет также потребоваться обработать кодировку строки JSON.В приведенном ниже примере предполагается кодировка UTF-8.
- В ответ JSON на сервер (
case 2
в исходном коде) также необходимо указывать длину.
Следует использовать следующий кодвместо этого:
#!/usr/bin/perl
use strict;
use warnings;
use JSON;
use IO::Socket;
my $socket = IO::Socket::INET->new(
PeerHost => '127.0.0.1',
PeerPort => '22',
Proto => 'tcp',
) or
die "cannot connect to the server $!\n";
print "connected to the server\n";
sub read_bytes($$) {
my($socket, $length) = @_;
my $result = '';
print "ATTEMPT TO READ ${length}\n";
while ($length > 0) {
my $received = $socket->read($result, $length, length($result));
die "socket error: $!\n" unless defined($received);
die "unexpected EOF\n" unless $received;
$length -= $received;
}
print "READ '${result}'\n";
return($result);
}
while (1) {
my $length = unpack("N", read_bytes($socket, 4));
my $json = read_bytes($socket, $length);
my $data = JSON->new->utf8->decode($json);
print $data->{type}, "\n";
if ($data->{type} == 2) {
my $response = {
type => 0,
point => [5, 4],
};
my $resp_json = JSON->new->utf8->encode($response);
print "JSON: ${resp_json}\n";
my $packet = pack('NA*', length($resp_json), $resp_json);
print "PACKET: ", unpack('H*', $packet), "\n";
$socket->write($packet);
}
}
Поскольку у меня нет доступа к вашему серверу, я использовал sshd
на моей локальной машине, что, конечно, не отправляет мне JSON.Но это показывает, что чтение работает: -)
$ perl dummy.pl
connected to the server
ATTEMPT TO READ 4
READ 'SSH-'
ATTEMPT TO READ 1397966893
^C
Вывод для примера ответа на сервер будет:
JSON: {"type":0,"point":[5,4]}
PACKET: 000000187b2274797065223a302c22706f696e74223a5b352c345d7d