Bio, es decir, bloqueando IO. Durante el proceso de comunicación de mensajes basado en Socket, el servidor Socket proporciona servicios al exterior, y el cliente Socket puede establecer una conexión con el servidor Socket, luego enviar datos de solicitud, luego esperar a que el servidor Socket se procese y devolver el resultado de procesamiento (respuesta).
Según la comunicación bio, el servidor Socket bloqueará, es decir, cada vez que la conexión Socket a un cliente sea aceptada durante el proceso de escucha, la solicitud debe procesarse y en este momento, otros clientes conectados solo pueden bloquear y esperar. Se puede ver que la capacidad de procesamiento del servidor Socket en este modo es muy limitada, y el cliente solo puede esperar hasta que el servidor esté inactivo y maneje la solicitud.
Implementación de la comunicación biológica
El siguiente se basa en el modelo BIO para implementar la lógica de un servidor de socket simple que se comunica con el cliente Socket, y tiene una comprensión perceptiva de este método de comunicación. La lógica específica se describe de la siguiente manera:
1. El cliente Socket se conecta al servidor Socket y envía los datos "Yo soy el cliente N.";
2. El servidor Socket escucha el puerto de servicio y recibe los datos de solicitud del cliente. Si los datos de la solicitud comienzan con "Yo soy el cliente", responde al cliente "Soy el servidor y usted es el enésimo cliente";
La implementación del servidor Socket es la siguiente:
paquete org.shirdrn.java.communications.bio; import java.io.ioException; import java.io.inputstream; import java.io.outputstream; import java.net.serversocket; import java.net.socket; / *** Socket Server basado en bio** @author shieldrn*/ public class SimpleBiotCpServer extiende el hilo {/ ** Número de puerto de servicio*/ privado int port = 8888; / ** Asignar número*/ private static int a la secuencia del cliente = 0; public SimpleBioTCPServer (int Port) {this.port = port; } @Override public void run () {socket socket = null; intente {Serversocket Serversocket = new Serversocket (this.port); while (true) {Socket = Serversocket.accept (); // escucha esto.handlemessage (socket); // HandLemessage (Socket); // manejar una solicitud de cliente conectada}} Catch (ioException e) {E.PrintStackTrace (); }} / ** * Manejar una conexión de socket de cliente * @param socket Socket * @throws ioexception * / private void HandLemessage (Socket Socket) lanza IOException {inputStream in = Socket.getInputStream (); // stream: client-> servidor (read) outputStream out = Socket.getOutputStream (); // stream: servidor-> cliente (escribir) int recibeBytes; byte [] recibeBuffer = new Byte [128]; String ClientMessage = ""; if ((recibeBytes = in.read (recibeBuffer))! =-1) {clientMessage = new String (recibeBuffer, 0, recibeBytes); if (clientMessage.Startswith ("I Am The Client")) {String ServerResponsewords = "Soy el servidor, y usted es el" + (++ secuencia) + "TH Client"; out.write (serverResponsewords.getBytes ()); }} out.flush (); System.out.println ("Servidor: recibe ClientMessage->" + ClientMessage); } public static void main (String [] args) {SimpleBioTCPserver Server = new SimpleBioTCPserver (1983); servidor.start (); }} La implementación anterior no realiza un procesamiento de excepción complejo.
La implementación del cliente Socket es la siguiente:
paquete org.shirdrn.java.communications.bio; import java.io.ioException; import java.io.inputstream; import java.io.outputstream; import java.net.socket; import java.net.unknownHosTexception; import java.util.date; / ** * Cliente de socket basado en bio * * @author shieldrn */ public class SimpleBiotCpClient {private String iPaddress; Puerto privado int; privado estático int pos = 0; public SimpleBioTCPClient () {} public SimpleBiotCpClient (String iPaddress, int port) {this.ipaddress = ipaddress; this.port = puerto; } / *** Conéctese al servidor de socket y simule el envío de datos de solicitud* @param datos de solicitud de datos* / public void send (byte [] data) {socket socket = null; OutputStream out = null; InputStream in = null; intente {socket = new Socket (this.ipaddress, this.port); // conectar // Enviar una solicitud = Socket.getOutputStream (); out.write (datos); out.flush (); // recibir respuesta en = Socket.getInputStream (); int totalbytes = 0; int recibeBytes = 0; byte [] recibeBuffer = new Byte [128]; if ((recibeBytes = in.read (recibeBuffer))! =-1) {TotalBytes += recibeBytes; } String serverMessage = new String (RecibeBuffer, 0, recibeBytes); System.out.println ("Cliente: recibe ServerMessage->" + ServerMessage); } capt (desconocidoHosTexception e) {E.PrintStackTrace (); } catch (ioException e) {E.PrintStackTrace (); } catch (Exception e) {E.PrintStackTrace (); } Finalmente {try {// Envía una solicitud y recibe una respuesta, la comunicación se completa, cierre la conexión. cercar(); socket.close (); } catch (ioException e) {E.PrintStackTrace (); }}} public static void main (string [] args) {int n = 1; StringBuffer data = new StringBuffer (); Fecha de inicio = nueva fecha (); for (int i = 0; i <n; i ++) {data.delete (0, data.length ()); data.append ("Yo soy el cliente") .append (++ pos) .append ("."); SimpleBioTCPClient Client = new SimpleBioTCPClient ("localhost", 1983); Client.send (data.ToString (). getBytes ()); } Date end = new Date (); costo largo = end.gettime () - start.gettime (); System.out.println (n + "Solicitudes Costo" + Costo + "MS"); }} Primero inicie el proceso del servidor Socket SimpleBioTCPServer y luego ejecute el Socket Client SimpleBioTCPClient. Se puede ver que el servidor recibe los datos de solicitud y luego responde al cliente, y el cliente recibe los datos de respuesta del servidor.
En la implementación anterior, tanto el cliente Socket como el servidor se escriben y leen a la vez. En realidad, si la cantidad de datos es particularmente grande durante cada comunicación, el servidor no puede aceptarlo. Puede encenderse para leerlo y procesarlo al determinar el número de bytes de datos solicitados por el cliente.
Además, si la corriente mencionada anteriormente no está envuelta, habrá pérdidas de rendimiento en la práctica, como la incapacidad de amortiguar, etc.
Para los datos de recepción del servidor Socket, es mucho más conveniente si los datos de bytes leídos de múltiples bucles se pueden almacenar a través de un búfer de byte de longitud variable. Sin embargo, usando bytearRayOutputStream, por ejemplo:
ByteArRayOutputStream data = new ByTearRaReOutputStream (); data.write (RecibeBuffer, TotalBytes, TotalBytes + recibeBytes);
Prueba de comunicación biológica
Lo siguiente prueba la eficiencia del procesamiento del servidor de socket en un escenario con una gran cantidad de solicitudes.
El primer método: inicie 5000 clientes de socket a través de un bucle for y envíe una solicitud. El código es el siguiente:
public static void main (string [] args) {int n = 5000; StringBuffer data = new StringBuffer (); Fecha de inicio = nueva fecha (); for (int i = 0; i <n; i ++) {data.delete (0, data.length ()); data.append ("Yo soy el cliente") .append (++ pos) .append ("."); SimpleBioTCPClient Client = new SimpleBioTCPClient ("localhost", 1983); Client.send (data.ToString (). getBytes ()); } Date end = new Date (); costo largo = end.gettime () - start.gettime (); System.out.println (n + "Solicitudes Costo" + Costo + "MS"); } Después de las pruebas, se necesitan alrededor de 9864 ms, que son aproximadamente 10s.
El segundo método: inicie 5,000 hilos de clientes independientes y solicite al mismo tiempo, y el servidor cuenta:
paquete org.shirdrn.java.communications.bio; import java.io.ioException; import java.io.inputstream; import java.io.outputstream; import java.net.serversocket; import java.net.socket; import java.net.unknownHosTexception; import java.util.date; / ** * Prueba de comunicación de socket basada en bio * * @author shieldrn */ public class SimpleBiotCptest {static int threadCount = 5000; / *** Proceso del servidor de socket basado en bio** @author shieldrn*/ static class socketServer extiende el hilo {/ ** número de puerto de servicio*/ private int port = 8888; / ** Asignar un número al cliente*/ private static int secuence = 0; public socketServer (int puerto) {this.port = puerto; } @Override public void run () {socket socket = null; int contador = 0; intente {Serversocket Serversocket = new Serversocket (this.port); bandera booleana = falso; Fecha de inicio = nulo; while (true) {Socket = Serversocket.accept (); // escuchar // tiempo comienza if (! Flag) {start = new Date (); bandera = verdadero; } this.handlemessage (socket); // manejar una solicitud de cliente conectada si (++ contador == ThreadCount) {date end = new Date (); Long Last = end.gettime () - start.gettime (); System.out.println (ThreadCount + "Solicitudes Costo" + Last + "MS"); }}}} Catch (ioException e) {E.PrintStackTrace (); }} / ** * Manejar una conexión de socket de cliente * @param socket Socket * @throws ioexception * / private void HandLemessage (Socket Socket) lanza IOException {inputStream in = Socket.getInputStream (); // stream: client-> servidor (read) outputStream out = Socket.getOutputStream (); // stream: servidor-> cliente (escribir) int recibeBytes; byte [] recibeBuffer = new Byte [128]; String ClientMessage = ""; if ((recibeBytes = in.read (recibeBuffer))! =-1) {clientMessage = new String (recibeBuffer, 0, recibeBytes); if (clientMessage.Startswith ("I Am The Client")) {String ServerResponsewords = "Soy el servidor, y usted es el" + (++ secuencia) + "TH Client"; out.write (serverResponsewords.getBytes ()); }} out.flush (); System.out.println ("Servidor: recibe ClientMessage->" + ClientMessage); }} / ** * Hilo del cliente de socket basado en bio * * @author shieldrn * / static class SocketClient implementa runnable {private String ipaddress; Puerto privado int; / ** Los datos de solicitud se enviarán*/ Datos de cadena privada; public SocketClient (String iPaddress, int puerto) {this.ipaddress = iPaddress; this.port = puerto; } @Override public void run () {this.send (); } / *** Conéctese al servidor de socket y simule el envío de datos de solicitud* / public void send () {socket socket = null; OutputStream out = null; InputStream in = null; intente {socket = new Socket (this.ipaddress, this.port); // conectar // Enviar solicitud = Socket.getOutputStream (); out.write (data.getBytes ()); out.flush (); // recibir respuesta en = Socket.getInputStream (); int totalbytes = 0; int recibeBytes = 0; byte [] recibeBuffer = new Byte [128]; if ((recibeBytes = in.read (recibeBuffer))! =-1) {TotalBytes += recibeBytes; } String serverMessage = new String (RecibeBuffer, 0, recibeBytes); System.out.println ("Cliente: recibe ServerMessage->" + ServerMessage); } capt (desconocidoHosTexception e) {E.PrintStackTrace (); } catch (ioException e) {E.PrintStackTrace (); } catch (Exception e) {E.PrintStackTrace (); } Finalmente {try {// Envía una solicitud y recibe una respuesta, la comunicación se completa, cierre la conexión. cercar(); socket.close (); } catch (ioException e) {E.PrintStackTrace (); }}} public void setData (datos de cadena) {this.data = data; }} public static void main (string [] args) lanza la excepción {SocketServer Server = new SocketServer (1983); servidor.start (); Thread.sleep (3000); for (int i = 0; i <threadcount; i ++) {SocketClient Client = new SocketClient ("localhost", 1983); Client.setData ("Soy el cliente" + (i + 1) + "."); nuevo hilo (cliente) .Start (); Thread.sleep (0, 1); }}}Después de la prueba, se necesitan alrededor de 7110 ms, que son aproximadamente 7s, y no hay una gran mejora.
Mejoras de comunicación biológica
A través de las pruebas anteriores, podemos encontrar que cuando el servidor Socket procesa las solicitudes del cliente, se produce el bloqueo, lo que afecta seriamente la eficiencia del procesamiento concurrente de las solicitudes. De hecho, dentro del alcance de la capacidad de conexión del servidor Socket, la solicitud recibida puede ser independiente, para resolver el problema anterior mediante el procesamiento de solicitudes mediante una solicitud y un hilo. De esta manera, el lado del servidor tiene múltiples subprocesos de procesamiento correspondientes a las múltiples solicitudes del cliente, y la eficiencia de procesamiento se ha mejorado en cierta medida.
A continuación, reciba la solicitud a través de un solo hilo y luego delegue el grupo de subprocesos para realizar solicitudes de procesamiento concurrentes múltiples:
/ *** Proceso del servidor de socket basado en bio** @author shieldrn*/ static class socketServer extiende el hilo {/ ** número de puerto de servicio*/ private int port = 8888; / ** Asignar número al cliente*/ private static int secuence = 0; / ** Grupo de subprocesos para procesar solicitudes de clientes*/ PRIVADO EjecutorService Pool; public SocketServer (int Port, int PoolSize) {this.port = port; this.pool = Ejecutors.NewFixedThreadPool (PoolSize); } @Override public void run () {socket socket = null; int contador = 0; intente {Serversocket Serversocket = new Serversocket (this.port); bandera booleana = falso; Fecha de inicio = nulo; while (true) {Socket = Serversocket.accept (); // escuchar // El tiempo comienza si viene una solicitud if (! Flag) {start = new Date (); bandera = verdadero; } // Ponga la solicitud del cliente en el grupo de subprocesos para procesar a Pool.Execute (nuevo SolicHandler (Socket)); if (++ contador == ThreadCount) {date end = new Date (); Long Last = end.gettime () - start.gettime (); System.out.println (ThreadCount + "Solicitudes Costo" + Last + "MS"); }}} Catch (ioException e) {E.PrintStackTrace (); }} / ** * Clase de subproceso de procesamiento de solicitud de cliente * * @author shieldrn * / class requitsHandler implementa runnable {private socket socket; Public SolicHandler (socket socket) {this.socket = socket; } @Override public void run () {try {inputStream in = Socket.getInputStream (); // stream: client-> servidor (read) outputStream out = Socket.getOutputStream (); // stream: servidor-> cliente (escribir) int recibeBytes; byte [] recibeBuffer = new Byte [128]; String ClientMessage = ""; if ((recibeBytes = in.read (recibeBuffer))! =-1) {clientMessage = new String (recibeBuffer, 0, recibeBytes); if (clientMessage.Startswith ("I Am The Client")) {String ServerResponsewords = "Soy el servidor, y usted es el" + (++ secuencia) + "TH Client"; out.write (serverResponsewords.getBytes ()); }} out.flush (); System.out.println ("Servidor: recibe ClientMessage->" + ClientMessage); } catch (ioException e) {E.PrintStackTrace (); }}}}}}}}}Se puede ver que este método mejorado mejora la concurrencia de las solicitudes de procesamiento del servidor, pero cada solicitud debe ser procesada por un hilo. Una gran cantidad de solicitudes hacen que el servidor inicie una gran cantidad de procesos para el procesamiento, lo que también ocupa relativamente recursos del servidor.
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.