Perl客户端到Java服务器
我正在尝试编写一个perl客户端程序来连接到Java服务器应用程序(JDuplicate)。我发现java服务器使用DataInput.readUTF和DataInput.writeUTF方法,JDuplicate网站将其列为“Java的经过修改的UTF-8协议”。Perl客户端到Java服务器
我的测试程序是非常简单的,我试图发送客户端类型的数据,应该调用来自服务器的响应,但它只是超时:
#!/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);
我试过$的远程> send(pack(“U”,“...”));我试过“使用utf8;”,我试过binmode($ remote,“:utf8”),我试过发送纯ASCII文本,没有任何回应。
我可以看到使用tcpdump发送的数据,全部在一个数据包中,但服务器本身对它不做任何处理(除了数据包之外)。
有什么额外的我需要做以满足Java的“修改”的utf实现吗?
谢谢。
你必须正确地贯彻protocol:
首先,计算为代表的
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: [email protected]\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]
完美!这正是我所期待的。我现在可以像预期的那样来回沟通。谢谢。 –
不客气!我很乐意提供帮助。 –
这与您的问题的主要部分无关,但我想我会解释API预期的“Java的已修改的UTF-8”是什么;它是UTF-8,除了UTF-16代理对被编码为自己的代码点,而不是通过直接在UTF-8中编码的对来代替代表。例如,采取字符U+1D11E MUSICAL SYMBOL G CLEF
。
- 在UTF-8中,它被编码为四个字节0。
- 在UTF-16中,因为它超出了
U+FFFF
,所以它使用代理对0xD834 0xDD1E
编码。 - 在“修改后的UTF-8”中,它给出了代理对码点的UTF-8编码:也就是说,您将
"\uD834\uDD1E"
编码为UTF-8,给出ED A0 B4 ED B4 9E
,它恰好是完全6个字节长。
当使用这种格式,Java将同样使用非法超长形式C0 80
而不是编码它们为空值编码任何嵌入的空值,确保有从来没有在“修订的UTF-8”字符串的任何嵌入的空值。
如果你不发送BMP或任何空之外的任何字符,虽然没有从真实的东西差异;)
好信息,谢谢澄清。 –
什么是Java代码? –