4 votes

Pourquoi IO::Socket::Async n'émet-il pas un "a" final?

Je me demandais si quelqu'un sait comment contourner l'encodage de IO::Socket::Async, en particulier les inconvénients décrits par ceci:

Par exemple, si l'encodage UTF-8 est utilisé et que le dernier octet du paquet décodé est "a", cela ne sera pas émis car le prochain paquet peut inclure un caractère de combinaison qui devrait former un seul graphème ensemble. Les caractères de contrôle (comme \n) servent toujours de limites de graphèmes, donc tout protocole basé sur du texte qui utilise des retours à la ligne ou des octets nuls comme terminaux n'auront pas besoin d'une considération spéciale.

Cela cause actuellement que mes sockets omettent le dernier caractère des messages, mais je ne sais pas comment contourner cela. J'ai essayé de convertir la Connection en un Channel puis juste d'envoyer un pseudo \n dedans, simulant la fin de l'entrée pour le message, mais cela n'a pas fonctionné. Comment puis-je contourner cette bizarrerie dans l'encodage UTF-8?

Voici le MVP pour reproduire ceci:

sub listen(Int $port) {
  react {
    whenever IO::Socket::Async.listen('0.0.0.0', $port) -> $connection {
      whenever $connection.Supply -> $data {
        say $data;
        $connection.print: $data;
      }
    }
  }
}

listen(9999);

Maintenant, si vous accédez au port 9999 sur votre machine locale avec des données qui ne se terminent pas par \n, vous verrez que le dernier octet est ignoré.

8voto

Jonathan Worthington Points 10914

Ce n'est pas un "inconvénient"; c'est simplement Raku reflétant le fonctionnement d'Unicode. Si vous savez que vous avez seulement besoin de gérer l'ASCII ou le Latin-1, alors spécifiez-le :

whenever $connection.Supply(:enc) -> $data { # or :enc
    ...
}

Si vous souhaitez gérer du texte Unicode, alors il est nécessaire de prendre en compte le fait que recevoir, par exemple, le point de code pour la lettre "a", ne fournit pas suffisamment d'informations pour transmettre un caractère complet, puisque le prochain point de code reçu dans le prochain paquet pourrait être un caractère combinant, tel qu'un accent aigu à placer sur le "a". Notez qu'une Str en Raku est une structure de données au niveau des caractères (dans d'autres langages, les chaînes sont souvent des octets ou des points de code, ce qui crée des problèmes différents qui sont largement invisibles pour ceux qui se soucient uniquement du texte en anglais !)

Tout protocole réseau bien conçu fournira un moyen de savoir quand la fin du contenu texte a été atteinte. Certains protocoles, comme HTTP, spécifient explicitement la longueur en octets du contenu, on peut donc travailler au niveau des octets (:bin) et décoder le résultat après avoir vu autant d'octets. D'autres peuvent utiliser la fermeture de la connexion ou les sauts de ligne.

En conclusion, les sémantiques de chaîne de caractères ou d'IO::Socket::Async (et ailleurs en Raku) ne sont pas en elles-mêmes un problème, mais elles peuvent mettre en évidence des problèmes de conception dans les protocoles.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X