Bio, c'est-à-dire bloquant IO. Pendant le processus de communication des messages basé sur Socket, le serveur de socket fournit des services à l'extérieur et le client de socket peut établir une connexion au serveur de socket, puis envoyer des données de demande, puis attendre que le serveur de socket soit traité et renvoyer le résultat de traitement (réponse).
Sur la base de la communication bio, le serveur de socket bloquera, c'est-à-dire que chaque fois que la connexion de socket à un client est acceptée pendant le processus d'écoute, la demande doit être traitée et, à l'heure actuelle, d'autres clients connectés ne peuvent que bloquer et attendre. On peut voir que la capacité de traitement du serveur de socket dans ce mode est très limitée, et le client ne peut qu'attendre que le serveur soit inactif et gère la demande.
Mise en œuvre de la communication bio
Ce qui suit est basé sur le modèle BIO pour implémenter la logique d'un simple serveur de socket communiquant avec le client de socket et avoir une compréhension perceptuelle de cette méthode de communication. La logique spécifique est décrite comme suit:
1. Le client Socket se connecte au serveur de socket et envoie les données "Je suis le client N.";
2. Le serveur de socket écoute le port de service et reçoit les données de demande du client. Si les données de demande commencent par "Je suis le client", il répond au client "Je suis le serveur et vous êtes le nième client";
L'implémentation du serveur de socket est la suivante:
package org.shirdrn.java.communications.bio; Importer java.io.ioException; import java.io.inputStream; import java.io.outputStream; import java.net.serversocket; import java.net.socket; / ** * Socket Server basé sur Bio * * @Author Shieldrn * / classe publique SimpleBiotCPSserver étend Thread {/ ** Numéro de port de service * / Private int port = 8888; / ** attribuer le numéro * / private static int à la séquence client = 0; public SimpleBiotCPServer (int port) {this.port = port; } @Override public void run () {socket socket = null; try {serversocket serversocket = new serversocket (this.port); while (true) {socket = serversocket.accept (); // écoute ceci.HandleMessage (socket); // HandleMessage (socket); // Gérer une demande client connectée}} catch (ioException e) {e.printStackTrace (); }} / ** * Gérer une connexion de socket client * @param socket socket socket * @throws ioException * / private void handlemesage (socket socket) lève ioException {inputStream dans = socket.getInputStream (); // Stream: Client-> Server (Read) OutputStream Out = socket.getOutputStream (); // Stream: Server-> Client (Write) int recesebytes; octet [] recesebuffer = nouveau octet [128]; String clientMessage = ""; if ((receseBytes = in.read (recesebuffer))! = - 1) {clientMessage = new String (ReceaBuffer, 0, receseBytes); if (clientMessage.startswith ("je suis le client")) {String ServerResponsewords = "Je suis le serveur, et vous êtes la" ++ séquence) + "th Client". out.write (serverResponsewords.getBytes ()); }} out.flush (); System.out.println ("Server: reçoit ClientMessage->" + ClientMessage); } public static void main (String [] args) {SimpleBiotCPServer Server = new SimpleBiotCPServer (1983); server.start (); }} La mise en œuvre ci-dessus n'effectue pas un traitement d'exceptions complexes.
L'implémentation du client de socket est la suivante:
package org.shirdrn.java.communications.bio; Importer java.io.ioException; import java.io.inputStream; import java.io.outputStream; import java.net.socket; import java.net.unknownhostException; Importer java.util.date; / ** * Client de socket basé sur Bio * * @author shieldrn * / classe publique SimpleBiotCPClient {private String iPaddress; port int privé; Int POS statique privé = 0; public SimpleBiotCPClient () {} public SimpleBiotCPClient (String iPaddress, int port) {this.ipAddress = iPaddress; this.port = port; } / ** * Connectez-vous au serveur de socket et simulez les données de la demande d'envoi * @param Données Données de demande * / public void Send (byte [] data) {socket socket = null; OutputStream out = null; InputStream dans = null; essayez {socket = new socket (this.ipaddress, this.port); // connect // Envoi une demande = socket.getOutputStream (); out.write (données); out.flush (); // reçoit une réponse dans = socket.getInputStream (); int totalbytes = 0; int recesebytes = 0; octet [] recesebuffer = nouveau octet [128]; if ((receseBytes = in.read (recesebuffer))! = - 1) {TotalBytes + = receseBytes; } String ServerMessage = new String (ReceaSbuffer, 0, ReceseBytes); System.out.println ("Client: reçoit ServerMessage->" + ServerMessage); } catch (inconnuhostException e) {e.printStackTrace (); } catch (ioException e) {e.printStackTrace (); } catch (exception e) {e.printStackTrace (); } Enfin {try {// Envoyer une demande et recevoir une réponse, la communication est terminée, fermer la connexion Out.close (); joindre(); socket.close (); } catch (ioException e) {e.printStackTrace (); }}} public static void main (String [] args) {int n = 1; StringBuffer data = new StringBuffer (); Date start = new Date (); for (int i = 0; i <n; i ++) {data.delete (0, data.length ()); data.append ("je suis le client") .Apnd (++ pos) .append ("."); Client SimpleBiotCPClient = new SimpleBiotCPClient ("LocalHost", 1983); client.send (data.toString (). GetBytes ()); } Date fin = new Date (); long coût = end.getTime () - start.getTime (); System.out.println (N + "Demandes Cost" + Cost + "MS."); }} Démarrez d'abord le processus Socket Server SimpleBiotCPServer, puis exécutez le client de socket SimpleBiotCPClient. On peut voir que le serveur reçoit les données de demande, puis répond au client, et que le client reçoit les données de réponse du serveur.
Dans l'implémentation ci-dessus, le client de socket et le serveur sont écrits et lus immédiatement. En réalité, si la quantité de données est particulièrement importante au cours de chaque communication, le serveur ne peut pas l'accepter. Il peut boucler pour le lire et le traiter lors de la détermination du nombre d'octets de données demandés par le client.
De plus, si le flux susmentionné n'est pas enveloppé, il y aura des pertes de performances dans la pratique, comme l'incapacité à tampon, etc.
Pour les données de réception du serveur de socket, il est beaucoup plus pratique si les données d'octets lues à partir de plusieurs boucles peuvent être stockées via un tampon d'octet de longueur variable. Cependant, en utilisant ByteArrayOutputStream, par exemple:
ByTearRayOutputStream data = new ByteArrayOutputStream (); Data.Write (ReceeBuffer, TotalBytes, TotalBytes + ReceyBytes);
Test de communication bio
Le suivant teste l'efficacité du traitement du serveur de socket dans un scénario avec un grand nombre de demandes.
La première méthode: Démarrez 5000 clients Socket via une boucle pour une boucle et envoyez une demande. Le code est le suivant:
public static void main (String [] args) {int n = 5000; StringBuffer data = new StringBuffer (); Date start = new Date (); for (int i = 0; i <n; i ++) {data.delete (0, data.length ()); data.append ("je suis le client") .Apnd (++ pos) .append ("."); Client SimpleBiotCPClient = new SimpleBiotCPClient ("LocalHost", 1983); client.send (data.toString (). GetBytes ()); } Date fin = new Date (); long coût = end.getTime () - start.getTime (); System.out.println (N + "Demandes Cost" + Cost + "MS."); } Après les tests, il faut environ 9864 ms, soit environ 10 s.
La deuxième méthode: démarrez 5 000 threads clients indépendants et demandez en même temps, et le serveur compte:
package org.shirdrn.java.communications.bio; Importer java.io.ioException; import java.io.inputStream; import java.io.outputStream; import java.net.serversocket; import java.net.socket; import java.net.unknownhostException; Importer java.util.date; / ** * Test de communication du socket basé sur Bio * * @author shieldrn * / classe publique SimpleBiotCPTest {static int threadcount = 5000; / ** * Processus de serveur de socket basé sur Bio * * @Author Shieldrn * / STATIC CLASS SOCKETSERVER étend Thread {/ ** Numéro de port de service * / Private int port = 8888; / ** Attribuez un nombre au client * / private static int Sequence = 0; public socketserver (int port) {this.port = port; } @Override public void run () {socket socket = null; int counter = 0; try {serversocket serversocket = new serversocket (this.port); booléen drapeau = false; Date start = null; while (true) {socket = serversocket.accept (); // écoute // le temps démarre si (! Flag) {start = new Date (); Flag = true; } this.HandleMessage (socket); // gére une demande du client connecté if (++ compteur == ThreadCount) {date End = new Date (); Long Last = end.getTime () - start.getTime (); System.out.println (ThreadCount + "Demandes Cost" + Last + "MS."); }}}} catch (ioException e) {e.printStackTrace (); }} / ** * Gérer une connexion de socket client * @param socket socket socket * @throws ioException * / private void handlemesage (socket socket) lève ioException {inputStream dans = socket.getInputStream (); // Stream: Client-> Server (Read) OutputStream Out = socket.getOutputStream (); // Stream: Server-> Client (Write) int recesebytes; octet [] recesebuffer = nouveau octet [128]; String clientMessage = ""; if ((receseBytes = in.read (recesebuffer))! = - 1) {clientMessage = new String (ReceaBuffer, 0, receseBytes); if (clientMessage.startswith ("je suis le client")) {String ServerResponsewords = "Je suis le serveur, et vous êtes la" ++ séquence) + "th Client". out.write (serverResponsewords.getBytes ()); }} out.flush (); System.out.println ("Server: reçoit ClientMessage->" + ClientMessage); }} / ** * Thread client de socket basé sur Bio * * @author shieldrn * / classe statique SocketClient implémente Runnable {private String iPaddress; port int privé; / ** Demander des données à envoyer * / des données de chaîne privées; public socketClient (String iPaddress, int port) {this.ipaddress = iPaddress; this.port = port; } @Override public void run () {this.send (); } / ** * Connectez-vous au serveur de socket et simulez les données de demande d'envoi * / public void Send () {socket socket = null; OutputStream out = null; InputStream dans = null; essayez {socket = new socket (this.ipaddress, this.port); // connect // Envoyer la demande = socket.getOutputStream (); out.write (data.getBytes ()); out.flush (); // reçoit une réponse dans = socket.getInputStream (); int totalbytes = 0; int recesebytes = 0; octet [] recesebuffer = nouveau octet [128]; if ((receseBytes = in.read (recesebuffer))! = - 1) {TotalBytes + = receseBytes; } String ServerMessage = new String (ReceaSbuffer, 0, ReceseBytes); System.out.println ("Client: reçoit ServerMessage->" + ServerMessage); } catch (inconnuhostException e) {e.printStackTrace (); } catch (ioException e) {e.printStackTrace (); } catch (exception e) {e.printStackTrace (); } Enfin {try {// Envoyer une demande et recevoir une réponse, la communication est terminée, fermer la connexion Out.close (); joindre(); socket.close (); } catch (ioException e) {e.printStackTrace (); }}} public void setData (String data) {this.data = data; }} public static void main (String [] args) lève une exception {socketserver server = new socketserver (1983); server.start (); Thread.Sleep (3000); for (int i = 0; i <threadCount; i ++) {socketClient client = new socketClient ("localhost", 1983); client.setData ("Je suis le client" + (i + 1) + "."); nouveau thread (client) .start (); Thread.Sleep (0, 1); }}}Après les tests, il faut environ 7110 ms, soit environ 7s, et il n'y a pas de grande amélioration.
Améliorations de la communication bio
Grâce aux tests ci-dessus, nous pouvons constater que lorsque le serveur de socket traite les demandes du client, le blocage se produit, ce qui affecte sérieusement l'efficacité du traitement simultané des demandes. En fait, dans le cadre de la capacité de connexion du serveur de socket, la demande reçue peut être indépendante, afin de résoudre le problème ci-dessus en traitant les demandes par une demande et un thread. De cette façon, le côté serveur a plusieurs threads de traitement correspondant aux multiples demandes du client, et l'efficacité de traitement a été améliorée dans une certaine mesure.
Ci-dessous, recevez la demande via un seul thread, puis déléguez le pool de threads pour effectuer des demandes de traitement simultanées multiples:
/ ** * Processus de serveur de socket basé sur Bio * * @Author Shieldrn * / STATIC CLASS SOCKETSERVER étend Thread {/ ** Numéro de port de service * / Private int port = 8888; / ** Attribuez un numéro au client * / private static int séquence = 0; / ** Pool de thread pour le traitement des demandes des clients * / Pool de service d'exécution privé; Public SockeTServer (port int, int poolSize) {this.port = port; this.pool = exécutors.newFixEdThreadPool (poolSize); } @Override public void run () {socket socket = null; int counter = 0; try {serversocket serversocket = new serversocket (this.port); booléen drapeau = false; Date start = null; while (true) {socket = serversocket.accept (); // écoute // le temps démarre si une demande vient si (! Flag) {start = new Date (); Flag = true; } // Mettez la demande du client dans le pool de threads pour traiter le pool.exécute (nouveau demandeur de demande (socket)); if (++ counter == ThreadCount) {date End = new Date (); Long Last = end.getTime () - start.getTime (); System.out.println (ThreadCount + "Demandes Cost" + Last + "MS."); }}} catch (ioException e) {e.printStackTrace (); }} / ** * Classe de thread de traitement de demande de demande du client * * @author shieldrn * / class demandehandler implémente runnable {private socket socket; Public DequehHandler (socket socket) {this.socket = socket; } @Override public void run () {try {inputStream in = socket.getInputStream (); // Stream: Client-> Server (Read) OutputStream Out = socket.getOutputStream (); // Stream: Server-> Client (Write) int recesebytes; octet [] recesebuffer = nouveau octet [128]; String clientMessage = ""; if ((receseBytes = in.read (recesebuffer))! = - 1) {clientMessage = new String (ReceaBuffer, 0, receseBytes); if (clientMessage.startswith ("je suis le client")) {String ServerResponsewords = "Je suis le serveur, et vous êtes la" ++ séquence) + "th Client". out.write (serverResponsewords.getBytes ()); }} out.flush (); System.out.println ("Server: reçoit ClientMessage->" + ClientMessage); } catch (ioException e) {e.printStackTrace (); }}}}}}}}}On peut voir que cette méthode améliorée améliore la concurrence des demandes de traitement du serveur, mais chaque demande doit être traitée par un thread. Un grand nombre de demandes provoquent le démarrage du serveur pour démarrer un grand nombre de processus de traitement, qui occupe également relativement les ressources du serveur.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.