Био, то есть блокировка io. Во время процесса связи сообщений на основе сокетов сервер Socket предоставляет услуги снаружи, и клиент Socket может установить соединение с сервером сокета, а затем отправлять данные запроса, а затем дождаться обработки сервера сокета и вернуть результат обработки (ответ).
Основываясь на био связи, сервер сокетов будет блокировать, то есть каждый раз, когда подключение к сокету с клиентом принимается во время процесса прослушивания, запрос должен обрабатывать, и в настоящее время другие подключенные клиенты могут блокировать и ждать. Можно видеть, что возможность обработки сервера сокета в этом режиме очень ограничена, и клиент может подождать только до тех пор, пока сервер не станет холостовым и обрабатывает запрос.
Био коммуникация реализация
Ниже основывается на био -модели для реализации логики простого сервера сокета, связывающегося с клиентом сокета, и иметь восприятие понимания этого метода связи. Конкретная логика описывается следующим образом:
1. Клиент сокета подключается к серверу сокета и отправляет данные «Я - клиент N.»;
2. Сервер сокетов слушает сервисный порт и получает данные запроса клиента. Если данные запроса начинаются с «Я клиент», это отвечает на клиента «Я сервер, а вы - NTH Client.»;
Реализация сервера сокета следующая:
пакет org.shirdrn.java.communications.bio; импортировать java.io.ioexception; импортировать java.io.inputstream; импортировать java.io.outputstream; импортировать java.net.serversocket; импортировать java.net.socket; / *** Socket Server на основе Bio** @author shieldrn*/ public class simplebiotcpserver extends {/ ** Номер порта сервиса*/ private int port = 8888; / ** Назначить номер*/ private static int к клиентской последовательности = 0; public simplebiotcpserver (int port) {this.port = port; } @Override public void run () {сокет сокет = null; try {serversocket serversocket = new Serversocket (this.port); while (true) {socket = serversocket.accept (); // послушать это. Handlemessage (сокет); // handlemessage (сокет); // Обработка подключенного клиентского запроса}} catch (ioException e) {e.printstacktrace (); }} / ** * Обработка подключения к клиенту сокета * @param stocket client socket * @throhs ioexception * / private void handlemessage (сокет сокета) бросает ioexception {inputstream in = socket.getinputstream (); // Stream: Client-> Server (Read) outputStream out = socket.getOutputStream (); // Stream: Server-> Client (write) int receationbytes; byte [] recebuffer = новый байт [128]; String clientMessage = ""; if ((chectyBytes = in.read (receatbuffer))! =-1) {clientMessage = new String (checteBuffer, 0, checteBytes); if (clientMessage.startSwith ("I Am Client")) {String ServerResponseWord = "Я сервер, а вы -" + (++ последовательность) + "th Client."; out.write (serverresponsewords.getbytes ()); }} out.flush (); System.out.println ("Сервер: получает ClientMessage->" + ClientMessage); } public static void main (string [] args) {simpleBiotCpserver Server = new SimpleBiotCpserver (1983); Server.Start (); }} Приведенная выше реализация не выполняет сложную обработку исключений.
Реализация клиента сокета выглядит следующим образом:
пакет org.shirdrn.java.communications.bio; импортировать java.io.ioexception; импортировать java.io.inputstream; импортировать java.io.outputstream; импортировать java.net.socket; Импорт java.net.unknownhostexception; импортировать java.util.date; / ** * Cocket Client на основе Bio * * @author shieldrn */ public class simplebiotcpclient {private String iPaddress; частный порт int; частный статический int pos = 0; public simplebiotcpclient () {} public simplebiotcpclient (string ipaddress, int port) {this.ipaddress = ipaddress; this.port = порт; } / *** Подключиться к серверу сокета и моделировать данные запроса отправки данных @param данных запроса данных* / public void send (byte [] data) {socket socket = null; OutputStream Out = null; InputStream in = null; try {socket = new Socket (this.ipaddress, this.port); // подключить // Отправить запрос = socket.getOutputStream (); out.write (data); out.flush (); // Приема ответа в = socket.getInputStream (); int totalbytes = 0; int atebytes = 0; byte [] recebuffer = новый байт [128]; if ((receatbytes = in.read (receatbuffer))! =-1) {totalbytes += chectyBytes; } String servermessage = new String (CreteBuffer, 0, CETESBYTES); System.out.println ("Client: получает ServerMessage->" + ServerMessage); } catch (Unknownhostexception e) {e.printstackTrace (); } catch (ioException e) {e.printstackTrace (); } catch (Exception e) {e.printstackTrace (); } наконец {try {// Отправить запрос и получить ответ, общение завершается, закройте соединение Out.close (); in.close (); Socket.Close (); } catch (ioException e) {e.printstackTrace (); }}} public static void main (string [] args) {int n = 1; StringBuffer Data = new StringBuffer (); Дата начала = новая дата (); for (int i = 0; i <n; i ++) {data.delete (0, data.length ()); data.append («Я клиент») .append (++ pos) .append ("."); Simplebiotcpclient client = new Simplebiotcpclient ("Localhost", 1983); client.send (data.tostring (). getbytes ()); } Date end = new Date (); Long Soyd = end.getTime () - start.getTime (); System.out.println (n + "Запрос затрат" + Стоимость + "MS."); }} Сначала запустите процесс Socket Server SimplyBiotcpserver, а затем запустите SomplebiotCpclient Client Socket. Можно видеть, что сервер получает данные запроса, а затем отвечает на клиента, и клиент получает данные ответа от сервера.
В приведенной выше реализации как клиент, так и сервер написаны и сразу читаются. В действительности, если объем данных особенно велик во время каждой связи, сервер не может его принять. Он может цикл для чтения и обработки при определении количества байтов данных, запрашиваемых клиентом.
Кроме того, если вышеупомянутый поток не обернут, на практике будут потери производительности, такие как неспособность буфера и т. Д.
Для получения данных сервера сокета это гораздо удобнее, если байтовые данные, считываемые из нескольких циклов, можно хранить через байтовый буфер с переменной длиной. Однако, например, с использованием Bytearrayoutputstream:
BytearRayOutputStream data = new BytearRayOutputStream (); Data.Write (CETERBUFFER, TotalBytes, TotalBytes + CETEBYBYTES);
Биологический тест
Следующие проверяют эффективность обработки сервера сокета в сценарии с большим количеством запросов.
Первый метод: запустить клиентов 5000 сокетов через петлю и отправить запрос. Код заключается в следующем:
public static void main (string [] args) {int n = 5000; StringBuffer Data = new StringBuffer (); Дата начала = новая дата (); for (int i = 0; i <n; i ++) {data.delete (0, data.length ()); data.append («Я клиент») .append (++ pos) .append ("."); Simplebiotcpclient client = new Simplebiotcpclient ("Localhost", 1983); client.send (data.tostring (). getbytes ()); } Date end = new Date (); Long Soyd = end.getTime () - start.getTime (); System.out.println (n + "Запрос затрат" + Стоимость + "MS."); } После тестирования это занимает около 9864 мс, что составляет около 10 с.
Второй метод: запустите 5000 независимых клиентских потоков и запросить одновременно, а сервер имеет значение:
пакет org.shirdrn.java.communications.bio; импортировать java.io.ioexception; импортировать java.io.inputstream; импортировать java.io.outputstream; импортировать java.net.serversocket; импортировать java.net.socket; Импорт java.net.unknownhostexception; импортировать java.util.date; / ** * Тест связи сокета на основе Bio * * @author Shieldrn */ Public Class SimpleBiotCptest {static int threadCount = 5000; / *** Процесс сервера сокета на основе Bio** @author shieldrn*/ static class socketserver extends {/ ** Номер порта сервиса*/ private int port = 8888; / ** Назначьте число клиенту*/ private static int sequence = 0; public socketserver (int port) {this.port = port; } @Override public void run () {сокет сокет = null; int счетчик = 0; try {serversocket serversocket = new Serversocket (this.port); логический флаг = false; Дата начала = null; while (true) {socket = serversocket.accept (); // Слушать // время начинается if (! Flag) {start = new Date (); flag = true; } this.handlemessage (сокет); // Обработка подключенного клиентского запроса if (++ counter == threadcount) {date end = new Date (); long last = end.getTime () - start.getTime (); System.out.println (ThreadCount + "Запрос затрат" + last + "ms."); }}}} catch (ioException e) {e.printstacktrace (); }} / ** * Обработка подключения к клиенту сокета * @param stocket client socket * @throhs ioexception * / private void handlemessage (сокет сокета) бросает ioexception {inputstream in = socket.getinputstream (); // Stream: Client-> Server (Read) outputStream out = socket.getOutputStream (); // Stream: Server-> Client (write) int receationbytes; byte [] recebuffer = новый байт [128]; String clientMessage = ""; if ((chectyBytes = in.read (receatbuffer))! =-1) {clientMessage = new String (checteBuffer, 0, checteBytes); if (clientMessage.startSwith ("I Am Client")) {String ServerResponseWord = "Я сервер, а вы -" + (++ последовательность) + "th Client."; out.write (serverresponsewords.getbytes ()); }} out.flush (); System.out.println ("Сервер: получает ClientMessage->" + ClientMessage); }} / ** * Поток клиента сокета на основе Bio * * @author Shieldrn * / Static Class SocketClient реализует runnable {private String iPaddress; частный порт int; / ** Запрос данных, которые будут отправлены*/ частные строковые данные; public socketClient (String iPaddress, int port) {this.ipaddress = iPaddress; this.port = порт; } @Override public void run () {this.send (); } / *** Подключиться к серверу сокета и моделировать данные запроса отправки* / public void send () {socket Socket = null; OutputStream Out = null; InputStream in = null; try {socket = new Socket (this.ipaddress, this.port); // подключить // Отправить запрос = socket.getOutputStream (); out.write (data.getbytes ()); out.flush (); // Приема ответа в = socket.getInputStream (); int totalbytes = 0; int atebytes = 0; byte [] recebuffer = новый байт [128]; if ((receatbytes = in.read (receatbuffer))! =-1) {totalbytes += chectyBytes; } String servermessage = new String (CreteBuffer, 0, CETESBYTES); System.out.println ("Client: получает ServerMessage->" + ServerMessage); } catch (Unknownhostexception e) {e.printstackTrace (); } catch (ioException e) {e.printstackTrace (); } catch (Exception e) {e.printstackTrace (); } наконец {try {// Отправить запрос и получить ответ, общение завершается, закройте соединение Out.close (); in.close (); Socket.Close (); } catch (ioException e) {e.printstackTrace (); }}} public void setData (String Data) {this.Data = data; }} public static void main (string [] args) бросает исключение {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 («Я клиент» + (i + 1) + ».»); новый поток (клиент) .start (); Thread.sleep (0, 1); }}}После тестирования это занимает около 7110 мс, что составляет около 7 с, и нет большого улучшения.
Улучшения биологической связи
Благодаря вышеупомянутым тестам мы можем обнаружить, что когда сервер сокета обрабатывает запросы от клиента, происходит блокирование, что серьезно влияет на эффективность одновременной обработки запросов. Фактически, в рамках возможности подключения сервера сокета полученный запрос может быть независимым, чтобы решить вышеуказанную проблему, обрабатывая запросы по одному запросу и одному потоку. Таким образом, на стороне сервера есть несколько потоков обработки, соответствующих нескольким запросам клиента, и эффективность обработки была улучшена в определенной степени.
Ниже получите запрос через один поток, а затем делегируйте пул потоков для выполнения многопоточных запросов на одновременную обработку:
/ *** Процесс сервера сокета на основе Bio** @author shieldrn*/ static class socketserver extends {/ ** Номер порта сервиса*/ private int port = 8888; / ** Назначить номер клиенту*/ private static int sequence = 0; / ** Пул потоков для обработки запросов клиентов*/ private recementervice Pool; public socketserver (int port, int poolsize) {this.port = port; this.pool = executors.newfixedthreadpool (poolsize); } @Override public void run () {сокет сокет = null; int счетчик = 0; try {serversocket serversocket = new Serversocket (this.port); логический флаг = false; Дата начала = null; while (true) {socket = serversocket.accept (); // Слушать // время начинается, если запрос приходит, если (! Flag) {start = new Date (); flag = true; } // Поместите запрос клиента в пул потоков для обработки pool.execute (new RequestHandler (сокет)); if (++ counter == threadcount) {date end = new Date (); long last = end.getTime () - start.getTime (); System.out.println (ThreadCount + "Запрос затрат" + last + "ms."); }}} catch (ioException e) {e.printstacktrace (); }} / ** * Класс обработки запросов клиента * * @Author SHIELDRN * / CLASS RequestRHandler реализует Runnable {Private Socket Socket; public request handler (сокет сокета) {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 receationbytes; byte [] recebuffer = новый байт [128]; String clientMessage = ""; if ((chectyBytes = in.read (receatbuffer))! =-1) {clientMessage = new String (checteBuffer, 0, checteBytes); if (clientMessage.startSwith ("I Am Client")) {String ServerResponseWord = "Я сервер, а вы -" + (++ последовательность) + "th Client."; out.write (serverresponsewords.getbytes ()); }} out.flush (); System.out.println ("Сервер: получает ClientMessage->" + ClientMessage); } catch (ioException e) {e.printstackTrace (); }}}}}}}}}Можно видеть, что этот улучшенный метод повышает параллелизм запросов на обработку сервера, но каждый запрос должен обрабатывать потоком. Большое количество запросов заставляет сервер запустить большое количество процессов для обработки, что также относительно занимает ресурсы сервера.
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.