Biografia, isto é, bloqueando io. Durante o processo de comunicação de mensagens baseado em soquete, o servidor de soquete fornece serviços para o exterior e o cliente de soquete pode estabelecer uma conexão com o servidor de soquete, enviar dados de solicitação e aguardar o processo do servidor de soquete e retornar o resultado do processamento (resposta).
Com base na comunicação biológica, o servidor de soquete será bloqueado, ou seja, sempre que a conexão de soquete com um cliente é aceita durante o processo de escuta, a solicitação deve ser processada e, neste momento, outros clientes conectados só podem bloquear e esperar. Pode -se observar que a capacidade de processamento do servidor de soquete nesse modo é muito limitada e o cliente só pode esperar até que o servidor esteja ocioso e lida com a solicitação.
Implementação de comunicação biológica
A seguir, é baseada no modelo bio para implementar a lógica de um servidor de soquete simples que se comunica com o cliente de soquete e tem uma compreensão perceptiva desse método de comunicação. A lógica específica é descrita da seguinte forma:
1. O cliente de soquete se conecta ao servidor de soquete e envia os dados "Eu sou o cliente N.";
2. O servidor de soquete ouve a porta de serviço e recebe os dados de solicitação do cliente. Se os dados da solicitação começarem com "eu sou o cliente", ele responderá ao cliente "eu sou o servidor e você é o enésimo cliente.";
A implementação do servidor de soquete é a seguinte:
pacote org.shirdrn.java.communications.bio; importar java.io.ioException; importar java.io.inputStream; importar java.io.OutputStream; importar java.net.serversocket; importar java.net.socket; / *** servidor de soquete baseado no bio** @author shieldrn*/ public class SimpleBiotCPServer estende o thread {/ ** número da porta de serviço*/ private int porta = 8888; / ** atribuir número*/ private static int à sequência do cliente = 0; public SimpleBioTCPServer (int porta) {this.port = port; } @Override public void run () {soquete de soquete = null; tente {serverSocket ServerSocket = new ServerSocket (this.port); while (true) {socket = serversocket.accept (); // Ouça this.HandleMessage (soquete); // handleMessage (soquete); // lidera uma solicitação de cliente conectada}} catch (ioexception e) {e.printStackTrace (); }} / ** * lidar com uma conexão de soquete do cliente * @param soquete soquete do cliente * @throws ioexception * / private void handleMessage (soquete) lança IoException {inputStream in = soket.getInputInputStream (); // Stream: client-> server (read) outputStream Out = Socket.getOutputStream (); // stream: server-> client (write) int recebeBytes; byte [] recebaBuffer = novo byte [128]; String clientMessage = ""; if ((REPETBYTES = in.Read (ReceberBuffer))! =-1) {clientMessage = new String (ReceberBuffer, 0, ReceberBytes); if (clientmessage.startswith ("eu sou o cliente")) {string serverResponsewords = "eu sou o servidor e você é a" sequência + (++) + "th cliente"; out.Write (ServerResponsewords.getBytes ()); }} out.flush (); System.out.println ("Server: recebe ClientMessage->" + ClientMessage); } public static void main (string [] args) {SimpleBiotCPServer Server = new SimpleBiotCPServer (1983); server.start (); }} A implementação acima não realiza processamento complexo de exceção.
A implementação do cliente de soquete é a seguinte:
pacote org.shirdrn.java.communications.bio; importar java.io.ioException; importar java.io.inputStream; importar java.io.OutputStream; importar java.net.socket; importar java.net.unknownhostException; importar java.util.date; / ** * cliente de soquete com base no bio * * @author shieldrn */ public class simplebiotcpclient {private string ipaddress; private int porta; estático privado int pos = 0; public SimpleBiotCpClient () {} public SimpleBioTCPClient (string ipaddress, int porta) {this.ipaddress = ipaddress; this.port = porta; } / *** Conecte -se ao servidor de soquete e simule dados de solicitação de envio* @param Data Solicle Data* / public void send (byte [] dados) {soquete soquete = null; OutputStream out = null; InputStream in = null; tente {socket = new Socket (this.ipaddress, this.port); // CONNECT // Envie uma solicitação para fora = Socket.getOutputStream (); out.write (dados); out.flush (); // recebe resposta em = soket.getInputStream (); int totalbytes = 0; int recebeBytes = 0; byte [] recebaBuffer = novo byte [128]; if ((REPETBYTES = in.Read (REPETBUFFER))! =-1) {totalBytes += RecendBytes; } String serverMessage = new String (ReceberBuffer, 0, ReceberBytes); System.out.println ("Client: recebe ServerMessage->" + ServerMessage); } catch (desconhecidohostException e) {e.printStackTrace (); } catch (ioexception e) {e.printStackTrace (); } catch (Exceção e) {e.printStackTrace (); } finalmente {tente {// Envie uma solicitação e receba uma resposta, a comunicação é concluída, feche a conexão OUT.Close (); in.Close (); Socket.Close (); } catch (ioexception e) {e.printStackTrace (); }}} public static void main (string [] args) {int n = 1; StringBuffer Data = new StringBuffer (); Data start = new date (); for (int i = 0; i <n; i ++) {data.delete (0, data.length ()); data.append ("Eu sou o cliente") .append (++ pos) .append ("."); Simplesbiotcpclient client = new simplesbiotcpclient ("localhost", 1983); client.send (data.toString (). getBytes ()); } Data final = new Date (); long custo = end.gettime () - start.gettime (); System.out.println (n + "solicita custo" + custo + "ms."); }} Primeiro inicie o processo do Socket Server SimpleBioTCPServer e, em seguida, execute o Socket Client SimpleBioTCPClient. Pode -se observar que o servidor recebe os dados da solicitação e depois responde ao cliente, e o cliente recebe os dados de resposta do servidor.
Na implementação acima, o cliente do soquete e o servidor são gravados e lidos de uma só vez. Na realidade, se a quantidade de dados for particularmente grande durante cada comunicação, o servidor não poderá aceitá -lo. Ele pode fazer um loop para ler e processá -lo ao determinar o número de bytes de dados solicitados pelo cliente.
Além disso, se o fluxo acima mencionado não estiver envolvido, haverá perdas de desempenho na prática, como a incapacidade de buffer etc.
Para dados de recebimento do servidor de soquete, é muito mais conveniente se os dados de bytes lidos em vários loops puderem ser armazenados através de um buffer de byte de comprimento variável. No entanto, usando bytearrayOutputStream, por exemplo:
ByteArrayOutputStream Data = new ByteArrayOutputStream (); Data.Write (ReceberBuffer, Totalbytes, TotalBytes + ReceberBytes);
Teste de comunicação biológica
O seguinte teste a eficiência do processamento do servidor de soquete em um cenário com um grande número de solicitações.
O primeiro método: inicie 5000 clientes de soquete por meio de loop e envie uma solicitação. O código é o seguinte:
public static void main (string [] args) {int n = 5000; StringBuffer Data = new StringBuffer (); Data start = new date (); for (int i = 0; i <n; i ++) {data.delete (0, data.length ()); data.append ("Eu sou o cliente") .append (++ pos) .append ("."); Simplesbiotcpclient client = new simplesbiotcpclient ("localhost", 1983); client.send (data.toString (). getBytes ()); } Data final = new Date (); long custo = end.gettime () - start.gettime (); System.out.println (n + "solicita custo" + custo + "ms."); } Após o teste, são necessários cerca de 9864ms, que são cerca de 10s.
O segundo método: Inicie 5.000 threads de clientes independentes e solicitem ao mesmo tempo, e o servidor conta:
pacote org.shirdrn.java.communications.bio; importar java.io.ioException; importar java.io.inputStream; importar java.io.OutputStream; importar java.net.serversocket; importar java.net.socket; importar java.net.unknownhostException; importar java.util.date; / ** * Teste de comunicação de soquete com base no bio * * @author shieldrn */ public class SimpleBiotCpTest {static int threadCount = 5000; / *** Processo do servidor de soquete com base no bio** @author shieldrn*/ sticketServer de classe estática estende thread {/ ** número da porta de serviço*/ private int porta = 8888; / ** Atribua um número ao cliente*/ private estático int sequência = 0; public SocketServer (int porta) {this.port = port; } @Override public void run () {soquete de soquete = null; int contador = 0; tente {serverSocket ServerSocket = new ServerSocket (this.port); bandeira booleana = false; Data inicial = nulo; while (true) {socket = serversocket.accept (); // Ouça // O tempo começa se (! Sinalizador) {start = new Date (); bandeira = true; } this.HandleMessage (soquete); // manipula uma solicitação de cliente conectada if (++ contador == threadCount) {date end = new Date (); long last = end.gettime () - start.gettime (); System.out.println (ThreadCount + "Solicita custo" + Last + "MS."); }}}} catch (ioexception e) {e.printStackTrace (); }} / ** * lidar com uma conexão de soquete do cliente * @param soquete soquete do cliente * @throws ioexception * / private void handleMessage (soquete) lança IoException {inputStream in = soket.getInputInputStream (); // Stream: client-> server (read) outputStream Out = Socket.getOutputStream (); // stream: server-> client (write) int recebeBytes; byte [] recebaBuffer = novo byte [128]; String clientMessage = ""; if ((REPETBYTES = in.Read (ReceberBuffer))! =-1) {clientMessage = new String (ReceberBuffer, 0, ReceberBytes); if (clientmessage.startswith ("eu sou o cliente")) {string serverResponsewords = "eu sou o servidor e você é a" sequência + (++) + "th cliente"; out.Write (ServerResponsewords.getBytes ()); }} out.flush (); System.out.println ("Server: recebe ClientMessage->" + ClientMessage); }} / ** * thread do cliente com base no bio * * @author shieldrn * / classe estática implementos de soquete runnable {private string iPaddress; private int porta; / ** Solicitar dados a serem enviados*/ Dados de sequência privada; public SocketClient (string ipaddress, int porta) {this.ipaddress = ipaddress; this.port = porta; } @Override public void run () {this.send (); } / *** Conecte -se ao servidor de soquete e simule os dados de solicitação de envio* / public void send () {Socket Socket = null; OutputStream out = null; InputStream in = null; tente {socket = new Socket (this.ipaddress, this.port); // Connect // Enviar solicitação de saída = Socket.getOutputStream (); out.write (data.getBytes ()); out.flush (); // recebe resposta em = soket.getInputStream (); int totalbytes = 0; int recebeBytes = 0; byte [] recebaBuffer = novo byte [128]; if ((REPETBYTES = in.Read (REPETBUFFER))! =-1) {totalBytes += RecendBytes; } String serverMessage = new String (ReceberBuffer, 0, ReceberBytes); System.out.println ("Client: recebe ServerMessage->" + ServerMessage); } catch (desconhecidohostException e) {e.printStackTrace (); } catch (ioexception e) {e.printStackTrace (); } catch (Exceção e) {e.printStackTrace (); } finalmente {tente {// Envie uma solicitação e receba uma resposta, a comunicação é concluída, feche a conexão OUT.Close (); in.Close (); Socket.Close (); } catch (ioexception e) {e.printStackTrace (); }}} public void setData (dados da string) {this.data = data; }} public static void main (string [] args) lança exceção {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 ("Eu sou o cliente" + (i + 1) + "."); novo thread (cliente) .start (); Thread.sleep (0, 1); }}}Após o teste, são necessários 7110ms, que são cerca de 7s, e não há grandes melhorias.
Melhorias na comunicação biológica
Através dos testes acima, podemos descobrir que, quando o servidor de soquete processa solicitações do cliente, ocorre o bloqueio, o que afeta seriamente a eficiência do processamento simultâneo de solicitações. De fato, dentro do escopo do recurso de conexão do servidor de soquete, a solicitação recebida pode ser independente, de modo a resolver o problema acima, processando solicitações por uma solicitação e um thread. Dessa forma, o lado do servidor possui vários threads de processamento correspondentes às várias solicitações do cliente, e a eficiência do processamento foi aprimorada até certo ponto.
Abaixo, receba a solicitação através de um único thread e, em seguida, delegue o pool de threads para executar solicitações de processamento simultâneas com vários threads:
/ *** Processo do servidor de soquete com base no bio** @author shieldrn*/ sticketServer de classe estática estende thread {/ ** número da porta de serviço*/ private int porta = 8888; / ** Atribua número ao cliente*/ private estático int sequência = 0; / ** Pool de threads para processamento de solicitações do cliente*/ Pool privado de ExecutService; Public SocketServer (int porta, int poolsize) {this.port = port; this.pool = executores.newfixedThreadpool (PoolSize); } @Override public void run () {soquete de soquete = null; int contador = 0; tente {serverSocket ServerSocket = new ServerSocket (this.port); bandeira booleana = false; Data inicial = nulo; while (true) {socket = serversocket.accept (); // Ouça // O tempo começa se uma solicitação vier se (! Sinalizador) {start = new Date (); bandeira = true; } // Coloque a solicitação do cliente no pool de threads para processar pool.execute (novo requestHandler (soquete)); if (++ contador == threadCount) {date end = new Date (); long last = end.gettime () - start.gettime (); System.out.println (ThreadCount + "Solicita custo" + Last + "MS."); }}} catch (ioexception e) {e.printStackTrace (); }} / ** * Solicitação de cliente Classe de threads * * @author shieldrn * / classe requestHandler implementa Runnable {Socket Socket privado; public requestHandler (soquete) {this.socket = soket; } @Override public void run () {try {inputStream in = socket.getInputStream (); // Stream: client-> server (read) outputStream Out = Socket.getOutputStream (); // stream: server-> client (write) int recebeBytes; byte [] recebaBuffer = novo byte [128]; String clientMessage = ""; if ((REPETBYTES = in.Read (ReceberBuffer))! =-1) {clientMessage = new String (ReceberBuffer, 0, ReceberBytes); if (clientmessage.startswith ("eu sou o cliente")) {string serverResponsewords = "eu sou o servidor e você é a" sequência + (++) + "th cliente"; out.Write (ServerResponsewords.getBytes ()); }} out.flush (); System.out.println ("Server: recebe ClientMessage->" + ClientMessage); } catch (ioexception e) {e.printStackTrace (); }}}}}}}}}Pode -se observar que esse método aprimorado aprimora a simultaneidade das solicitações de processamento do servidor, mas cada solicitação deve ser processada por um thread. Um grande número de solicitações faz com que o servidor inicie um grande número de processos de processamento, o que também ocupa relativamente os recursos do servidor.
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.