2009-09-20 5 views
0

Au lieu d'utiliser un sélecteur de la manière habituelle, où pour chaque canal prêt un message peut être déterminé et envoyé, je voudrais choisir quelle connexion est actuellement prête et envoyer un message là-bas. Vraisemblablement, cela peut être fait en jetant tous les canaux dans un sélecteur pour les lire et les marquer prêts à être lus s'ils sortent, puis en faisant la même chose pour l'écriture, puis en choisissant parmi ceux que j'ai marqués prêts.Java nio, vérifiant si un canal est prêt pour la lecture, écrire

Est-ce une bonne idée, est-ce qu'il y a une meilleure façon de le faire, et que dois-je faire attention? Par exemple, les états Rox Tutorial"Si vous essayez de mélanger OP READ et OP WRITE, vous aurez rapidement des ennuis: l'implémentation de Windows est bloquée si vous le faites." Y a-t-il des pièges similaires ici? Quelle est la meilleure façon de mettre en œuvre:

boolean isReadyForRead(SocketChannel c); 
boolean isReadyForWrite(SocketChannel c); 

Répondre

2

Que diriez-vous quelque chose comme ça?

public static boolean isReadyForRead(SocketChannel socket) throws IOException { 
    return isReady(socket, SelectionKey.OP_READ); 
} 

public static boolean isReadyForWrite(SocketChannel socket) throws IOException { 
    return isReady(socket, SelectionKey.OP_WRITE); 
} 

public static boolean isReady(SocketChannel socket, int op) throws IOException { 
    // Setup 
    if (socket.isBlocking()) 
     throw new IllegalArgumentException("Socket must be in non-blocking mode"); 

    Selector selector = SelectorProvider.provider().openSelector(); 
    socket.register(selector, op); 

    // Real work 
    if (selector.selectNow() == 0) 
     return false; 
    // Just in case selector has other keys 
    return selector.selectedKeys().contains(socket.keyFor(selector)); 
} 

Cet appel est terriblement inefficace car il fait l'installation à chaque fois. Si vous avez une classe englobante, elle doit être déplacée. Si vous savez que le sélecteur ne contient qu'une seule touche, la dernière ligne peut être changée en "return true;".

Je fais juste cela pour m'amuser. Je ne peux pas penser à un scénario que cela sera utile. Select() est conçu pour vous indiquer l'état des sockets efficacement et tout le monde devrait l'utiliser directement.

+0

Y a-t-il des problèmes à le faire de cette façon, même si cela a été déplacé? (J'ai restauré la version originale de ma question.) –

+0

Je ne suis pas familier avec le problème mentionné dans le tutoriel, mais nous ne le faisons pas. Nous ne mixons pas READ/WRITE. Le jeu de clés ne sera pas mis à jour pour chaque appel, donc pas de problème de threading. –

6

Vous devez utiliser pour vérifier de votre SelectionKey si une prise est prêt pour la lecture ou d'écriture, lorsque le sélecteur se réveille.

Voici un tutoriel très utile sur écrire un NIO serveur et client http://rox-xmlrpc.sourceforge.net/niotut/

+0

Je voudrais savoir quand un canal spécifique est prêt et que les canaux n'ont pas de méthode .isReadyForRead(). Als, par "réveille" voulez-vous dire "quand .select() renvoie", ou parlez-vous d'une stratégie de threading? –

+1

+1 pour le pointeur vers le didacticiel – Mark

+0

C'est lorsque .select() renvoie. Cela est dû à une connexion nécessitant une lecture ou une écriture, ou si selector.select() est appelée. Vous devez ensuite parcourir les touches sélectionnées et vérifier si le sélecteur est prêt pour la lecture ou l'écriture. (Il y a quelques autres étapes mais elles sont toutes décrites dans le tutoriel). – Malaxeur

Questions connexes