Я переписываю свой сервер сокетов P5 в P6, используя IO::Socket::Async, но полученные данные усекаются на 1 символ в конце, и этот 1 символ получен при следующем соединении. Кто-то из группы Perl6 в Facebook (Джонатан Уортингтон) указал, что это может быть связано с тем, что строки и байты обрабатываются по-разному в P6. Цитата:
В Perl 6 строки и байты обрабатываются совершенно по-разному. Следует отметить, что строки работают на уровне графем. При получении данных Unicode возможно не только разделение многобайтовой последовательности на пакеты, но и последовательность с несколькими кодовыми точками. Например, один пакет может иметь в конце букву «а», а следующий — комбинированный острый ударение. Следовательно, он не может безопасно передать «а», пока не увидит, как начинается следующий пакет.
Мой P6 работает на MoarVM
use Data::Dump;
use experimental :pack;
my $socket = IO::Socket::Async.listen('0.0.0.0', 7000);
react {
whenever $socket -> $conn {
my $line = '';
whenever $conn {
say "Received --> "~$_;
$conn.print: &translate($_) if $_.chars ge 100;
$conn.close;
}
}
CATCH {
default {
say .^name, ': ', .Str;
say "handled in $?LINE";
}
}
}
sub translate($raw) {
my $rawdata = $raw;
$raw ~~ s/^\s+|\s+$//; # remove heading/trailing whitespace
my $minus_checksum = substr($raw, 0, *-2);
my $our_checksum = generateChecksum($minus_checksum);
my $data_checksum = ($raw, *-2);
# say $our_checksum;
return $our_checksum;
}
sub generateChecksum($minus_checksum) {
# turn string into Blob
my Blob $blob = $minus_checksum.encode('utf-8');
# unpack Blob into ascii list
my @array = $blob.unpack("C*");
# perform bitwise operation for each ascii in the list
my $dec +^= $_ for $blob.unpack("C*");
# only take 2 digits
$dec = sprintf("%02d", $dec) if $dec ~~ /^\d$/;
$dec = '0'.$dec if $dec ~~ /^[a..fA..F]$/;
$dec = uc $dec;
# convert it to hex
my $hex = sprintf '%02x', $dec;
return uc $hex;
}
Результат
Received --> $$0116AA861013034151986|10001000181123062657411200000000000010235444112500000000.600000000345.4335N10058.8249E00015
Received --> 0
Received --> $$0116AA861013037849727|1080100018112114435541120000000000000FBA00D5122500000000.600000000623.9080N10007.8627E00075
Received --> D
Received --> $$0108AA863835028447675|18804000181121183810421100002A300000100900000000.700000000314.8717N10125.6499E00022
Received --> 7
Received --> $$0108AA863835028447675|18804000181121183810421100002A300000100900000000.700000000314.8717N10125.6499E00022
Received --> 7
Received --> $$0108AA863835028447675|18804000181121183810421100002A300000100900000000.700000000314.8717N10125.6499E00022
Received --> 7
Received --> $$0108AA863835028447675|18804000181121183810421100002A300000100900000000.700000000314.8717N10125.6499E00022
Received --> 7
IO::Socket::Async
усекает данные. На самом деле P6 помогает вам предотвратить повреждение данных. P6 делает выбор разработчиков очевидным: байты или символы. ЛИБО Вы используете:bin
, поэтому данные представляют собой последовательность байтов. Таким образом, единицей передачи является байт. ИЛИ Данные представляют собой текст, последовательность то, что пользователь считает символ. Таким образом, логической единицей передачи является один символ за раз. Таким образом, P6 буферизует байты, чтобы обеспечить доставку целого символа только тогда, когда известно, что он завершен. Эта буферизация является следствием дизайна Unicode. - person raiph   schedule 24.11.2018