Perl-клиент для Java-сервера - PullRequest
2 голосов
/ 13 января 2010

Я пытаюсь написать клиентскую программу на Perl для подключения к серверу Java-приложения (JDuplicate). Я вижу, что сервер java использует методы DataInput.readUTF и DataInput.writeUTF, которые на веб-сайте JDuplicate перечислены как «модифицированный протокол Java UTF-8».

Моя тестовая программа довольно проста, я пытаюсь отправить данные клиентского типа, которые должны вызвать ответ от сервера, однако время ожидания истекло:

#!/usr/bin/perl

use strict;
use Encode;
use IO::Socket;

my $remote = IO::Socket::INET->new(
  Proto => 'tcp',
  PeerAddr => 'localhost',
  PeerPort => '10421'
) or die "Cannot connect to server\n";

$|++;

$remote->send(encode_utf8("CLIENTTYPE|JDSC#0.5.9#0.2"));
while (<$remote>) {
  print $_,"\n";
}
close($remote);

exit(0);

Я пробовал $ remote-> send (pack ("U", "...")); я пробовал "использовать utf8;", я пробовал binmode ($ remote, ": utf8 "), и я попытался отправить простой текст в формате ASCII, на который ничего не получено.

Я вижу, что данные отправляются с помощью tcpdump, все в одном пакете, но сам сервер ничего с этим не делает (кроме подтверждения пакета).

Есть ли что-то еще, что мне нужно сделать, чтобы удовлетворить "модифицированную" реализацию utf Java?

Спасибо.

Ответы [ 2 ]

4 голосов
/ 13 января 2010

Вы должны правильно реализовать протокол :

Сначала вычисляется общее количество байтов, необходимое для представления всех символов s. Если это число больше 65535, то выбрасывается UTFDataFormatException. В противном случае эта длина записывается в выходной поток точно так же, как метод writeShort; после этого записывается одно-, двух- или трехбайтовое представление каждого символа в строке s.

Как указано в документе для writeShort, он отправляет 16-разрядное количество в сетевом порядке.

В Perl это похоже на

sub sendmsg {
  my($s,$msg) = @_;

  die "message too long" if length($msg) > 0xffff;

  my $sent = $s->send(
    pack(n => (length($msg) & 0xffff)) .
    $msg
  );

  die "send: $!"    unless defined $sent;
  die "short write" unless $sent == length($msg) + 2;
}

sub readmsg {
  my($s) = @_;
  my $buf;
  my $nread;

  $nread = $s->read($buf, 2);
  die "read: $!"   unless defined $nread;
  die "short read" unless $nread == 2;

  my $len = unpack n => $buf;

  $nread = $s->read($buf, $len);
  die "read: $!"   unless defined $nread;
  die "short read" unless $nread == $len;

  $buf;
}

Хотя приведенный выше код не выполняет модифицированное кодирование UTF, он вызывает ответ:

my $remote = IO::Socket::INET->new(
  Proto => 'tcp',
  PeerAddr => 'localhost',
  PeerPort => '10421'
) or die "Cannot connect to server: $@\n";

my $msg = "CLIENTTYPE|JDSC#0.5.9#0.2";

sendmsg $remote, $msg;

my $buf = readmsg $remote;
print "[$buf]\n";

Выход:

[SERVERTYPE|JDuplicate#0.5.9 beta (build 584)#0.2]
3 голосов
/ 13 января 2010

Это не связано с основной частью вашего вопроса, но я подумал, что объясню, что такое «модифицированный Java UTF-8», которого ожидает API; это UTF-8, за исключением суррогатных пар UTF-16, закодированных как их собственные кодовые точки, вместо того, чтобы символы представляли парами, закодированными непосредственно в UTF-8. Например, возьмите символ U+1D11E MUSICAL SYMBOL G CLEF.

  • В UTF-8 он кодируется как четыре байта F0 9D 84 9E.
  • В UTF-16, поскольку он превышает U+FFFF, он кодируется с использованием суррогатной пары 0xD834 0xDD1E.
  • В «модифицированном UTF-8» ему присваивается кодировка UTF-8 кодовых точек суррогатной пары: то есть вы кодируете "\uD834\uDD1E" в UTF-8, что дает ED A0 B4 ED B4 9E, длина которого составляет шесть байтов. .

При использовании этого формата Java также будет кодировать любые внедренные нули, используя недопустимую чрезмерно длинную форму C0 80 вместо того, чтобы кодировать их как нули, гарантируя, что в строке «модифицированного UTF-8» никогда не будет никаких встроенных нулей. *

Если вы не отправляете никаких символов за пределы BMP или любых нулей, тем не менее, нет никакой разницы от реальной вещи;)

Вот некоторые документы, любезно предоставленные Sun .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...