Bio, das heißt, blockieren IO. Während des Socket-basierten Nachrichtenkommunikationsprozesses bietet der Socket-Server Dienste an der Außenseite, und der Socket-Client kann eine Verbindung zum Socket-Server herstellen, dann Anforderungsdaten senden, dann auf den Socket-Server warten und das Verarbeitungsergebnis zurückgeben (Antwort).
Basierend auf der Bio -Kommunikation blockiert der Socket -Server, dh jedes Mal, wenn die Socket -Verbindung zu einem Client während des Hörprozesses akzeptiert wird, muss die Anfrage bearbeitet werden und zu diesem Zeitpunkt können andere verbundene Clients nur blockieren und warten. Es ist zu erkennen, dass die Verarbeitungsfunktion des Socket -Servers in diesem Modus sehr begrenzt ist und der Client nur warten kann, bis der Server im Leerlauf ist und die Anforderung behandelt.
Implementierung von Biokommunikation
Das Folgende basiert auf dem BIO -Modell, um die Logik eines einfachen Socket -Servers zu implementieren, der mit dem Socket -Client kommuniziert, und ein Wahrnehmungsverständnis dieser Kommunikationsmethode zu haben. Die spezifische Logik wird wie folgt beschrieben:
1. Der Socket -Client stellt eine Verbindung zum Socket -Server her und sendet die Daten "Ich bin der Client N.".
2. Der Socket -Server hört auf den Serviceport und empfängt die Client -Anforderungsdaten. Wenn die Anforderungsdaten mit "Ich bin der Client" beginnt, reagiert sie auf den Client "Ich bin der Server und Sie sind der nte Client.";
Die Socket -Server -Implementierung ist wie folgt:
paket org.shirdrn.java.communications.bio; importieren java.io.ioException; importieren java.io.inputstream; importieren java.io.outputstream; importieren java.net.serversocket; importieren java.net.socket; / *** Socket Server basiert auf BIO** @Author Shieldrn*/ public class SimpleBiotCpServer erweitert Thread {/ ** Service Portnummer*/ private int port = 8888; / ** Nummer*/ private statische int der client sequence = 0; public SimpleBiotCpServer (int port) {this.port = port; } @Override public void run () {Socket Socket = null; versuche {serversocket serversocket = new ServerSocket (this.port); while (true) {socket = serversocket.accept (); // Hören Sie sich dies an. Handlemessage (Socket); // Handlemessage (Socket); // eine vernetzte Client -Anforderung}} catch (ioException e) {e.printstacktrace (); }} / ** * eine Client -Socket -Verbindung verwandeln * @param Socket Client -Socket * @throws ioException * / private void Handlemessage (Socket Socket) löst ioException {InputStream in = socket.getInputStream () aus; // Stream: client-> server (read) outputStream out = socket.getOutputStream (); // Stream: Server-> Client (Write) int recematytes; byte [] recemeBuffer = neues Byte [128]; String clientMessage = ""; if ((recesBytes = in.read (recemeBuffer))! if (ClientMessage.StartSwith ("Ich bin der Client")) {String ServerResponsewords = "Ich bin der Server, und Sie sind die" + (++ - Sequenz) + "Th Client". out.write (serverResponsewords.getBytes ()); }} out.flush (); System.out.println ("Server: empfängt ClientMessage->" + clientmessage); } public static void main (String [] args) {SimpleBiotCpServer Server = new SimpleBiotCpServer (1983); server.start (); }} Die obige Implementierung führt keine komplexe Ausnahmeverarbeitung durch.
Die Socket -Client -Implementierung lautet wie folgt:
paket org.shirdrn.java.communications.bio; importieren java.io.ioException; importieren java.io.inputstream; importieren java.io.outputstream; importieren java.net.socket; Importieren Sie java.net.unnownhostException; import Java.util.date; / ** * Socket -Client basierend auf Bio * * @Author Shieldrn */ public class SimpleBiotCPClient {private String iPaddress; privater Int -Port; private statische int pos = 0; public SimpleBiotCPClient () {} public SimpleBiotCPClient (String iPaddress, int port) {this.ipaddress = ipaddress; this.port = port; } / *** Stellen Sie eine Verbindung zum Socket -Server her und simulieren Sie das Senden von Anforderungsdaten* @Param Data Request Data* / public void senden (byte [] Daten) {Socket Socket = null; OutputStream out = null; InputStream in = null; try {socket = new Socket (this.ipaddress, this.port); // connec // eine Anforderung out = socket.getOutputStream () senden; out.write (Daten); out.flush (); // Antwort in = socket.getInputStream (); int TotalBytes = 0; int recemeBytes = 0; byte [] recemeBuffer = neues Byte [128]; if ((recesBytes = in.read (recemeBuffer))! } String servermessage = new String (recemeBuffer, 0, recesBytes); System.out.println ("Client: Empfängt ServerMessage->" + ServerMessage); } catch (unbekannteHostException e) {e.printstacktrace (); } catch (ioException e) {e.printstacktrace (); } catch (Ausnahme e) {e.printstacktrace (); } endlich {try {// eine Anfrage senden und eine Antwort erhalten, die Kommunikation ist abgeschlossen, schließen Sie die Verbindung out.close (); in.close (); socket.close (); } catch (ioException e) {e.printstacktrace (); }}} public static void main (String [] args) {int n = 1; StringBuffer data = new StringBuffer (); Datum start = neuer Datum (); für (int i = 0; i <n; i ++) {data.delete (0, data.length ()); Data.Append ("Ich bin der Client") .Append (++ pos) .Append ("."); SimpleBiotCPClient Client = new SimpleBiotcpclient ("Localhost", 1983); client.send (data.toString (). getBytes ()); } Date end = new Date (); long cost = end.getTime () - start.getTime (); System.out.println (n + "Anfragen Kosten" + Kosten + "MS."); }} Starten Sie zuerst den Socket -Server -Prozess SimpleBiotCpServer und führen Sie dann den Socket Client SimpleBiotCPClient aus. Es ist zu sehen, dass der Server die Anforderungsdaten empfängt und dann auf den Client reagiert und der Client die Antwortdaten vom Server erhält.
In der obigen Implementierung werden sowohl der Socket -Client als auch der Server sofort geschrieben und lesen. In Wirklichkeit kann der Server dies in Wirklichkeit nicht akzeptieren, wenn die Datenmenge besonders groß ist. Es kann eine Schleifen haben, um es zu lesen und zu verarbeiten, wenn die Anzahl der vom Client angeforderten Datenbytes ermittelt wird.
Wenn der oben genannte Strom nicht verpackt ist, werden in der Praxis Leistungsverluste wie die Unfähigkeit zum Puffer usw. auftreten.
Für Socket-Server, die Daten empfangen, ist es viel bequemer, wenn die von mehreren Schleifen gelesenen Bytedaten über einen Byte-Puffer variabler Länge gespeichert werden können. Zum Beispiel: Verwenden von BytearrayoutputStream:
BytearrayoutputStream data = new bytearrayoutputStream (); Data.Write (RecemeBuffer, TotalBytes, TotalBytes + RecreeBytes);
Biokommunikationstest
Die folgenden Tests testen die Effizienz der Socket -Server -Verarbeitung in einem Szenario mit einer großen Anzahl von Anforderungen.
Die erste Methode: Starten Sie 5000 Socket -Clients über eine für Schleife und senden Sie eine Anfrage. Der Code ist wie folgt:
public static void main (String [] args) {int n = 5000; StringBuffer data = new StringBuffer (); Datum start = neuer Datum (); für (int i = 0; i <n; i ++) {data.delete (0, data.length ()); Data.Append ("Ich bin der Client") .Append (++ pos) .Append ("."); SimpleBiotCPClient Client = new SimpleBiotcpclient ("Localhost", 1983); client.send (data.toString (). getBytes ()); } Date end = new Date (); long cost = end.getTime () - start.getTime (); System.out.println (n + "Anfragen Kosten" + Kosten + "MS."); } Nach dem Testen dauert es ungefähr 9864 ms, was ungefähr 10s sind.
Die zweite Methode: Starten Sie 5.000 unabhängige Client -Threads und fordern Sie gleichzeitig an, und der Server zählt:
paket org.shirdrn.java.communications.bio; importieren java.io.ioException; importieren java.io.inputstream; importieren java.io.outputstream; importieren java.net.serversocket; importieren java.net.socket; Importieren Sie java.net.unnownhostException; import Java.util.date; / ** * Socket -Kommunikationstest basierend auf Bio * * @Author Shieldrn */ public class SimpleBiotCptest {static int threadCount = 5000; / *** Socket -Serverprozess basierend auf Bio** @Author Shieldrn*/ statische Klasse SocketServer erweitert Thread {/ ** Service Portnummer*/ private int port = 8888; / ** dem Client eine Nummer zuweisen*/ private statische Int -Sequenz = 0; public Socketserver (int port) {this.port = port; } @Override public void run () {Socket Socket = null; int counter = 0; versuche {serversocket serversocket = new ServerSocket (this.port); boolesche Flagge = Falsch; Datum start = null; while (true) {socket = serversocket.accept (); // listen // Zeit beginnt if (! Flag) {start = new Date (); Flag = wahr; } this.handlemessage (Socket); // eine angeschlossene Client -Anforderung verarbeiten if (++ counter == threadCount) {Datum end = new Date (); last last = end.getTime () - start.getTime (); System.out.println (ThreadCount + "Anfragen kostete" + last + "ms."); }}}} catch (ioException e) {e.printstacktrace (); }} / ** * eine Client -Socket -Verbindung verwandeln * @param Socket Client -Socket * @throws ioException * / private void Handlemessage (Socket Socket) löst ioException {InputStream in = socket.getInputStream () aus; // Stream: client-> server (read) outputStream out = socket.getOutputStream (); // Stream: Server-> Client (Write) int recematytes; byte [] recemeBuffer = neues Byte [128]; String clientMessage = ""; if ((recesBytes = in.read (recemeBuffer))! if (ClientMessage.StartSwith ("Ich bin der Client")) {String ServerResponsewords = "Ich bin der Server, und Sie sind die" + (++ - Sequenz) + "Th Client". out.write (serverResponsewords.getBytes ()); }} out.flush (); System.out.println ("Server: empfängt ClientMessage->" + clientmessage); }} / ** * Socket -Client -Thread basierend auf Bio * * @author shieldrn * / static class SocketClient Implements Runnable {private String iPaddress; privater Int -Port; / ** Anforderungsdaten zu senden*/ private String -Daten; public socketClient (String iPaddress, int port) {this.ipaddress = ipaddress; this.port = port; } @Override public void run () {this.send (); } / *** Stellen Sie eine Verbindung zum Socket -Server her und simulieren Sie das Senden von Anforderungsdaten* / public void send () {Socket Socket = null; OutputStream out = null; InputStream in = null; try {socket = new Socket (this.ipaddress, this.port); // connect // Anforderung out = socket.getOutputStream (); out.write (data.getBytes ()); out.flush (); // Antwort in = socket.getInputStream (); int TotalBytes = 0; int recemeBytes = 0; byte [] recemeBuffer = neues Byte [128]; if ((recesBytes = in.read (recemeBuffer))! } String servermessage = new String (recemeBuffer, 0, recesBytes); System.out.println ("Client: Empfängt ServerMessage->" + ServerMessage); } catch (unbekannteHostException e) {e.printstacktrace (); } catch (ioException e) {e.printstacktrace (); } catch (Ausnahme e) {e.printstacktrace (); } endlich {try {// eine Anfrage senden und eine Antwort erhalten, die Kommunikation ist abgeschlossen, schließen Sie die Verbindung out.close (); in.close (); socket.close (); } catch (ioException e) {e.printstacktrace (); }}} public void setData (String -Daten) {this.data = data; }} public static void main (String [] args) löst eine Ausnahme aus {SocketServer Server = New SocketServer (1983); server.start (); Thread.sleep (3000); für (int i = 0; i <threadCount; i ++) {SocketClient Client = new SocketClient ("localhost", 1983); client.setData ("Ich bin der Client" + (i + 1) + "."); neuer Thread (Client) .Start (); Thread.sleep (0, 1); }}}Nach dem Testen dauert es ungefähr 7110 ms, was ungefähr 7s beträgt, und es gibt keine große Verbesserung.
Verbesserungen der Biokommunikation
Durch die oben genannten Tests können wir feststellen, dass, wenn der Socket -Server Anforderungen des Clients verarbeitet, Blockierung auftritt, was die Effizienz der gleichzeitigen Verarbeitung von Anforderungen ernsthaft beeinflusst. Tatsächlich kann die empfangene Anforderung im Rahmen der Verbindungskapazität des Socket -Servers unabhängig sein, um das obige Problem durch Verarbeitung von Anforderungen mit einer Anforderung und einem Thread zu lösen. Auf diese Weise verfügt die Serverseite über mehrere Verarbeitungs -Threads, die den mehreren Anforderungen des Kunden entsprechen, und die Verarbeitungseffizienz wurde bis zu einem gewissen Grad verbessert.
Erhalten Sie die Anforderung über einen einzelnen Thread und delegieren Sie dann den Thread-Pool, um die gleichzeitigen Verarbeitungsanforderungen mit mehreren Threads durchzuführen:
/ *** Socket -Serverprozess basierend auf Bio** @Author Shieldrn*/ statische Klasse SocketServer erweitert Thread {/ ** Service Portnummer*/ private int port = 8888; / ** dem Client zuweisen*/ private statische Int -Sequenz = 0; / ** Threadpool zur Bearbeitung von Client -Anfragen*/ privater Ausführender Pool; public Socketserver (int port, int poolsize) {this.port = port; this.pool = Executors.NewFixedThreadpool (poolsize); } @Override public void run () {Socket Socket = null; int counter = 0; versuche {serversocket serversocket = new ServerSocket (this.port); boolesche Flagge = Falsch; Datum start = null; while (true) {socket = serversocket.accept (); // listen // Zeit beginnt, wenn eine Anfrage kommt, wenn (! Flag) {start = new Date (); Flag = wahr; } // Die Client -Anforderung in den Thread -Pool eingeben, um pool.execute zu verarbeiten (neuer RequestHandler (Socket)); if (++ counter == threadCount) {Date end = new Date (); last last = end.getTime () - start.getTime (); System.out.println (ThreadCount + "Anfragen kostete" + last + "ms."); }}} catch (ioException e) {e.printstacktrace (); }} / ** * Client -Anforderungsverarbeitungs -Thread -Klasse * * @author shieldrn * / class RequestHandler implementiert Runnable {private Socket Socket; public RequestHandler (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 recematytes; byte [] recemeBuffer = neues Byte [128]; String clientMessage = ""; if ((recesBytes = in.read (recemeBuffer))! if (ClientMessage.StartSwith ("Ich bin der Client")) {String ServerResponsewords = "Ich bin der Server, und Sie sind die" + (++ - Sequenz) + "Th Client". out.write (serverResponsewords.getBytes ()); }} out.flush (); System.out.println ("Server: empfängt ClientMessage->" + clientmessage); } catch (ioException e) {e.printstacktrace (); }}}}}}}}}}Es ist ersichtlich, dass diese verbesserte Methode die Parallelität der Serververarbeitungsanforderungen verbessert, aber jede Anforderung muss über einen Thread verarbeitet werden. Eine große Anzahl von Anforderungen bewirkt, dass der Server eine große Anzahl von Prozessen für die Verarbeitung startet, was auch relativ die Serverressourcen belegt.
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.