一、回传协议接口和 TCP 方式实现 :
1. : :
import java.nio.channels.selectionkey; Importer java.io.ioException; Interface publique EchoprotoCol {void handleaccept (SELECTIONKEY KEY) lève ioException; VOID HandlereRead (SELECTIONKEKEY) lève IOException; Void HandleWrite (SELECTIONKEKEKEY) lève IOException; }2. 实现 :
import java.nio.channels. *; import java.nio.bytebuffer; Importer java.io.ioException; La classe publique TCPECHOSELECTORProtocol implémente Echoprotocol {private int bufsize; // Taille du tampon d'E / S public EchoselectorProtocol (int bufsize) {this.bufSize = bufSize; } public void handleAccept (SELECTIONKEKEY KEY) lève ioException {socketchannel clntchan = ((serversocketchannel) key.channel ()). accepte (); clntchan.configureBlocking (false); // doit être non bloquant pour enregistrer // enregistrer le sélecteur avec un nouveau canal pour lire et attacher le tampon d'octet clntchan.register (key.selector (), selectionkey.op_read, bytebuffer.allocate (bufSize)); } public void handleread (SELECTELKEY KEY) lève ioException {// Le canal de socket client a des données en attente socketchannel clntchan = (socketchannel) key.channel (); Bytebuffer buf = (bytebuffer) key.attachment (); long bytesRead = clntchan.read (buf); if (bytesRead == -1) {// L'autre fin a-t-elle terminé? clntchan.close (); } else if (bytesRead> 0) {// indique via la clé que la lecture / l'écriture est tous les deux intéressants maintenant. key.interestops (selectionKey.op_read | selectionKey.op_write); }} public void Handlewrite (SELECTIONKEKEY KEY) lève IOException {/ * * Le canal est disponible pour l'écriture, et la clé est valide (c'est-à-dire le canal client * non fermé). * / // Récupérer les données lues plus tôt ByteBuffer buf = (byteBuffer) key.attachment (); buf.flip (); // Préparez le tampon pour l'écriture de socketchannel clntchan = (socketchannel) key.channel (); clntchan.write (buf); if (! buf.hasremaining ()) {// tampon complètement écrit? // Il ne reste plus rien à ne pas intéresser à écrit key.interestops (selectionKey.op_read); } buf.compact (); // Faire de la place pour plus de données à lire en}}二、 Nio TCP 客户端:
Importer java.net.inetsocketAddress; import java.net.socketException; import java.nio.bytebuffer; import java.nio.channels.socketchannel; classe publique TCPECHOCLIentNonBlocking {public static void main (String args []) lève l'exception {String Server = "127.0.0.1"; // Nom du serveur ou adresse IP // Convertir la chaîne d'entrée en octets en utilisant le charset par défaut [] argument = "0123456789abcdefghijklmnopqrstuvwxyz" .getBytes (); int servport = 5500; // Créer un canal et défini sur socketchannel non bloquant clntchan = socketchannel.open (); clntchan.configureBlocking (false); // initier la connexion au serveur et interroger à plusieurs reprises jusqu'à terminer if (! Clntchan.connect (new InetsocketAddress (server, servport))) {while (! Clntchan.finishconnect ()) {System.out.print ("."); // faire autre chose}} bytebuffer writeBuf = byteBuffer.wrap (argument); ByteBuffer readBuf = byteBuffer.AllOcy (Argument.Length); int totalBytesrcvd = 0; // Total des octets reçus jusqu'à présent int bytesrcvd; // octets reçus dans la dernière lecture while (totalBytesrcvd <argument.length) {if (writeBuf.hasreMinging ()) {clntchan.write (writeBuf); } if ((bytesrcvd = clntchan.read (readbuf)) == -1) {throw new socketException ("connexion fermée prématurément"); } totalBytesrcvd + = bytesrcvd; System.out.print ("."); // faire quelque chose d'autre} System.out.println ("Reçu:" + // Converti en chaîne par défaut Charset new String (readbuf.array (), 0, totalBytesrcvd) .length ()); clntchan.close (); }}三、 Nio TCP 服务端:
Importer java.io.ioException; Importer java.net.inetsocketAddress; import java.nio.channels. *; Importer java.util.iterator; classe publique TCPSERVerselector {private static final int bufSize = 256; // Taille du tampon (octets) Timeout final statique final privé = 3000; // WAIT TIMEout (millisecondes) public static void main (String [] args) lève ioException {int [] ports = {5500}; // Créer un sélecteur pour multiplexer les prises d'écoute et les connexions sélecteur sélecteur = sélecteur.open (); // Créer un canal de socket d'écoute pour chaque port et le sélecteur de registre pour (port int: ports) {serversocketchannel listnChannel = serversocketchannel.open (); listnChannel.socket (). Bind (new IneTSocketAddress (port)); listnChannel.configureBlocking (false); // doit être non bloquant pour enregistrer // le sélecteur d'enregistrement avec le canal. La clé renvoyée est ignorée listnchannel.register (sélecteur, sélectionkey.op_accept); } // Créer un gestionnaire qui implémentera le protocole ProtoCol TCPPROTOCOL = nouveau TCPECHOSELECTORPROCOL (BUFSIZE); tandis que (true) {// s'exécute pour toujours, le traitement des opérations d'E / S disponibles // attendez qu'un canal soit prêt (ou délai d'expiration) if (Selector.Select (timeout) == 0) {// return # of Ready Chans System.out.print ("."); continuer; } // Obtenez Iterator sur le jeu de touches avec des E / S pour traiter Iterator <lelectionKey> keyiter = Selector.SelectedKeys (). Iterator (); while (keyiter.hasnext ()) {SelectionKey key = keyiter.next (); // La touche est un masque de bits // canal de socket serveur a des demandes de connexion en attente? if (key.isacceptable ()) {System.out.println ("---- accepter -----"); protocole.HandleAccept (clé); } // Le canal de socket client a des données en attente? if (key.isreadable ()) {System.out.println ("---- Read ------"); protocole.HandleRead (clé); } // Le canal de socket client est disponible pour l'écriture et // la clé est valide (c'est-à-dire le canal non fermé)? if (key.isvalid () && key.iswitable ()) {System.out.println ("---- écriture -----"); protocole.handlewrite (clé); } keyiter.remove (); // Supprimer de l'ensemble des touches sélectionnées}}}}°