Java NIO: Comment savoir quand SocketChannel read() est complète avec des non-blocage I/O

Je suis actuellement en utilisant un non-bloquant SocketChannel (Java 1.6) pour agir comme un client à un serveur Redis. Redis accepte plaine-des commandes de texte directement sur une prise, terminées par un CRLF et réagit comme un exemple rapide:

ENVOYER: "PING\r\n'

RECV: '+PONG\r\n'

Redis pouvez également retourner énorme réponses (en fonction de ce que vous demandez) avec de nombreuses sections de \r\n-résiliation de données qui font tous partie d'une seule et même réponse.

Je suis en utilisant une norme while(socket.read() > 0) {//ajout d'octets} boucle pour lire des octets à partir de la douille et de ré-assembler côté client dans une réponse.

NOTE: je ne suis pas à l'aide d'un Sélecteur, juste plusieurs, côté client SocketChannels connecté au serveur, en attente de service envoyer/recevoir des commandes.

Ce que je suis confus au sujet de qui est le contrat de la SocketChannel.read() méthode en mode sans blocage, plus précisément, comment savoir quand le serveur d'envoi et j'ai le message en entier.

J'ai quelques méthodes pour protéger contre le retour des trop vite et donner une chance de répondre, mais la seule chose que je suis bloqué sur est:

  1. Est-il jamais possible pour read() de retour octets, puis ultérieurement sur un retour d'appel de n octets, mais sur un autre appel ultérieur à nouveau de retour de quelques octets?

En gros, puis-je faire confiance que le serveur est en fait de répondre à moi si j'ai reçu au moins 1 octet, et finalement read() retourne 0 alors je sais que je suis fait, ou est-il possible que le serveur était occupé et peut-chute en arrière de quelques octets si je attendre et de continuer à essayer?

Si il peut continuer à envoyer des octets, même après une lecture() a renvoyé 0 octets (après précédentes lectures réussies), alors je n'ai aucune idée de comment savoir si le serveur est fait de me parler et de me confondre java.io.* le style de communication ne sais même lorsque le serveur est "fait", soit.

Que vous les gars savent lire ne retourne -1, sauf si la connexion est mort et ce sont standard à long terme DB connections, donc je ne serai pas de fermeture et d'ouverture sur chaque demande.

Je sais une réponse populaire (au moins pour ces NIO questions) ont été à regarder Grizzly, MINA ou Netty -- si possible, j'aimerais vraiment savoir comment tout cela fonctionne dans son état brut, avant l'adoption de certaines 3ème partie des dépendances.

Merci.

Question Bonus:

J'ai pensé à l'origine d'un blocage SocketChannel serait le chemin pour aller avec ce que je ne veux pas vraiment à l'appelant de faire quelque chose jusqu'à ce que je leur commande et de leur donner une réponse, de toute façon.

Si cela finit par être une meilleure façon d'y aller, j'ai été un peu confus en voyant que SocketChannel.lire() bloque aussi longtemps qu'il n'y a pas d'octets suffisante pour remplir le tampon... bref de la lecture de tout, octet par octet, je ne peux pas comprendre comment ce comportement par défaut est en fait destiné à être utilisé... je ne sais jamais le exacte la taille de la réponse est de retour à partir du serveur, donc mes appels à SocketChannel.read() toujours bloquer jusqu'à ce qu'un temps (à quel point je vois enfin que le contenu était assis dans la mémoire tampon).

Je ne suis pas très clair sur la bonne façon d'utiliser le blocage de la méthode, car il bloque toujours sur une lecture.

  • Ce n'est pas lié à NIO mais un protocole doit soit utiliser fixe la longueur des messages, envoyer la longueur du message de la première ou à la fin de chaque message unique avec un délimiteur.
  • Donc, en général, vous dites, à moins que j'ai des séparateurs ou des longueurs de travailler avec, je suis SOL? Le Redis protocole ne fait préciser ces choses, mais je dois convertir des octets pour les caractères, pièce repas, à la volée pour vérifier ces valeurs que j'ai lu, faisant de mon code réseau un enfer de beaucoup plus compliqué. J'espérais que je pourrais l'éviter.
  • J'ai peur que c'est le seul moyen sûr mais ce n'est pas si mauvais que ça. Aussi loin que je peux rassembler, le Redis protocole à la fin de chaque commande/répondre élément avec un CR/LF, de sorte que vous pouvez lire et d'accumuler des octets lors de la vérification pour CR/LF et de convertir votre tampon de caractères à la fin de chaque ligne.
  • biziclop - très bonne suggestion, je n'avais pas réellement pensé pour groupe sur \r\n limites, mais qui permettrait d'éviter que l'un octet-char de conversion les cas, je étais inquiet au sujet de (tentative de conversion unicode char avant de tous les octets sont disponibles). Merci!!!!
InformationsquelleAutor Riyad Kalla | 2011-02-07