バイオ、つまり、IOをブロックします。ソケットベースのメッセージ通信プロセス中、ソケットサーバーは外部にサービスを提供し、ソケットクライアントはソケットサーバーへの接続を確立し、リクエストデータを送信し、ソケットサーバーが処理され、処理結果(応答)を返すことができます。
バイオ通信に基づいて、ソケットサーバーはブロックされます。つまり、リスニングプロセス中にクライアントへのソケット接続が受け入れられるたびに、リクエストを処理する必要があり、現時点では他の接続されたクライアントはブロックして待機することができます。このモードでのソケットサーバーの処理機能は非常に限られており、クライアントはサーバーがアイドル状態になり、リクエストを処理するまで待つことができることがわかります。
バイオ通信の実装
以下は、ソケットクライアントと通信する単純なソケットサーバーのロジックを実装し、この通信方法を知覚的に理解するためのバイオモデルに基づいています。特定のロジックは次のように説明されています。
1.ソケットクライアントはソケットサーバーに接続し、「私はクライアントNです」というデータを送信します。
2.ソケットサーバーはサービスポートに耳を傾け、クライアント要求データを受信します。リクエストデータが「私はクライアントです」から始まる場合、それはクライアントに「私はサーバーであり、あなたはn番目のクライアントです」に応答します。
ソケットサーバーの実装は次のとおりです。
パッケージorg.shirdrn.java.communications.bio; java.io.ioexceptionをインポートします。 java.io.inputStreamをインポートします。 java.io.outputStreamをインポートします。 java.net.serversocketをインポートします。 java.net.socketをインポートします。 / *** bioのソケットサーバーベース** @author shieldrn*/ public class simplebiotcpserver拡張スレッド{/ **サービスポート番号*/ private int port = 8888; / **番号を割り当てる*/ private static intにクライアントシーケンス= 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(); // this.handlemessage(socket)を聞いてください。 // handlemessage(socket); //接続されたクライアントのリクエストを処理}} catch(ioException e){e.printstacktrace(); }} / ** *クライアントソケット接続を処理 * @paramソケットクライアントソケット * @throws ioexception * / private void handlemessage(socket socket)throws ioexception {inputstream in = socket.getInputStream(); //ストリーム:クライアント - >サーバー(読み取り)outputStream out = socket.getOutputStream(); //ストリーム:server-> client(write)int receivebytes; byte [] receivebuffer = new byte [128];文字列clientmessage = ""; if((receivebytes = in.read(receiveBuffer))!= -1){clientMessage = new String(receiveBuffer、0、receiveBytes); if(clientmessage.startswith( "i a a client")){string serverResponseWords = "私はサーバーです。 out.write(serverResponseWords.getBytes()); }} out.flush(); system.out.println( "server:culientmessage->" + 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をインポートします。 Import Java.util.date; / ** * bioに基づくソケットクライアント * * @author shieldrn */ public class simplebiotcpclient {private string iPaddress;プライベートインターポート; private static int pos = 0; public simpleBiotcpClient(){} public SimpleBiotcpClient(String iPaddress、int port){this.ipaddress = iPaddress; this.port = port; } / ***ソケットサーバーに接続し、リクエストデータの送信* @paramデータ要求データ* / public void send(byte [] data){socket socket = null; outputStream out = null; inputstream in = null; try {socket = new Socket(this.ipaddress、this.port); // connect //リクエストを送信= socket.getOutputStream(); out.write(data); out.flush(); //応答を受信= socket.getInputStream(); int totalbytes = 0; int receiveBytes = 0; byte [] receivebuffer = new byte [128]; if((receivebytes = in.read(receiveBuffer))!= -1){totalBytes += receiveBytes; } string serverMessage = new String(receiveBuffer、0、receiveBytes); 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();日付開始= new Date(); for(int i = 0; i <n; i ++){data.delete(0、data.length()); data.Append( "I Am the Client").append(++ pos).append( "。"); SimpleBioTCPCLIENTクライアント= new SimpleBiotCPClient( "LocalHost"、1983); client.send(data.toString()。getBytes()); } date end = new date(); long cost = end.getTime() - start.getTime(); System.out.println(n + "requests cost" + cost + "ms"); }}最初にSocket Server Process SimpleBiotCpserverを開始し、Socket Client SimpleBioTCPClientを実行します。サーバーが要求データを受信してからクライアントに応答し、クライアントがサーバーから応答データを受信することがわかります。
上記の実装では、ソケットクライアントとサーバーの両方が書き込まれ、一度に読み上げられます。実際には、各通信中にデータの量が特に大きい場合、サーバーはそれを受け入れることができません。クライアントが要求したデータバイトの数を決定するときに、読み取りおよび処理するためにループできます。
さらに、上記のストリームが包まれていない場合、バッファーの不能など、実際にはパフォーマンスの損失が発生します。
ソケットサーバーの受信データの場合、複数のループから読み取られたバイトデータを可変長バイトバッファーに保存できる場合、はるかに便利です。ただし、たとえば、bytearrayoutputStreamを使用してください。
bytearrayoutputStream data = new bytearrayoutputStream(); data.write(receivebuffer、totalbytes、totalbytes + receivebytes);
バイオ通信テスト
以下は、多数のリクエストを使用したシナリオでのソケットサーバー処理の効率をテストします。
最初の方法: forループを介して5000のソケットクライアントを開始し、リクエストを送信します。コードは次のとおりです。
public static void main(string [] args){int n = 5000; stringbuffer data = new StringBuffer();日付開始= new Date(); for(int i = 0; i <n; i ++){data.delete(0、data.length()); data.Append( "I Am the Client").append(++ pos).append( "。"); SimpleBioTCPCLIENTクライアント= new SimpleBiotCPClient( "LocalHost"、1983); client.send(data.toString()。getBytes()); } date end = new date(); long cost = end.getTime() - start.getTime(); System.out.println(n + "requests cost" + cost + "ms"); }テスト後、約10秒で約9864ミリ秒かかります。
2番目の方法: 5,000の独立したクライアントスレッドと同時にリクエストを開始すると、サーバーがカウントされます。
パッケージorg.shirdrn.java.communications.bio; java.io.ioexceptionをインポートします。 java.io.inputStreamをインポートします。 java.io.outputStreamをインポートします。 java.net.serversocketをインポートします。 java.net.socketをインポートします。 java.net.unknownhostexceptionをインポートします。 Import Java.util.date; / ** * bioに基づくソケット通信テスト * * @author shieldrn */ public class simplebiotcptest {static int threadcount = 5000; / *** bioに基づくソケットサーバープロセス/ **クライアントに番号を割り当てます*/ 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);ブールフラグ= false;日付開始= null; while(true){socket = serversocket.accept(); //聞きます//時間を開始するif(!flag){start = new date(); flag = true; } this.handlemessage(socket); //接続されたクライアント要求を処理するif(++ counter == threadcount){date end = new date(); long last = end.getTime() - start.getTime(); system.out.println(threadcount + "requests cost" + last + "ms"); }}}} catch(ioexception e){e.printstacktrace(); }} / ** *クライアントソケット接続を処理 * @paramソケットクライアントソケット * @throws ioexception * / private void handlemessage(socket socket)throws ioexception {inputstream in = socket.getInputStream(); //ストリーム:クライアント - >サーバー(読み取り)outputStream out = socket.getOutputStream(); //ストリーム:server-> client(write)int receivebytes; byte [] receivebuffer = new byte [128];文字列clientmessage = ""; if((receivebytes = in.read(receiveBuffer))!= -1){clientMessage = new String(receiveBuffer、0、receiveBytes); if(clientmessage.startswith( "i a a client")){string serverResponseWords = "私はサーバーです。 out.write(serverResponseWords.getBytes()); }} out.flush(); system.out.println( "server:culientmessage->" + clientMessage); }} / ** * bioに基づくソケットクライアントスレッド * * @author shieldrn * / static class socketclient runnable {private string ipaddress;プライベートインターポート; / **送信されるデータを要求*/プライベート文字列データ。 public socketclient(string iPaddress、int port){this.ipaddress = iPaddress; this.port = 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); // connect //リクエストを送信= socket.getOutputStream(); out.write(data.getBytes()); out.flush(); //応答を受信= socket.getInputStream(); int totalbytes = 0; int receiveBytes = 0; byte [] receivebuffer = new byte [128]; if((receivebytes = in.read(receiveBuffer))!= -1){totalBytes += receiveBytes; } string serverMessage = new String(receiveBuffer、0、receiveBytes); 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秒かかり、大きな改善はありません。
バイオコミュニケーションの改善
上記のテストを通じて、ソケットサーバーがクライアントからのリクエストを処理すると、ブロックが発生し、リクエストの同時処理の効率に深刻な影響を与えることがわかります。実際、Socket Serverの接続機能の範囲内で、受信した要求は独立しているため、1つのリクエストと1つのスレッドでリクエストを処理することで上記の問題を解決することができます。このようにして、サーバー側には、クライアントの複数のリクエストに対応する複数の処理スレッドがあり、処理効率はある程度改善されています。
以下では、単一のスレッドを介してリクエストを受け取り、スレッドプールを委任して、マルチスレッドの同時処理リクエストを実行します。
/ *** bioに基づくソケットサーバープロセス/ **クライアントに番号を割り当てます*/ private static int sequence = 0; / **クライアントリクエストを処理するためのスレッドプール*/ private executorserviceプール。 public socketserver(int port、int poolsize){this.port = port; this.pool = executors.newfixedthreadpool(poolsize); } @Override public void run(){socket socket = null; int counter = 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(socket))を処理します。 if(++ counter == threadcount){date end = new date(); long last = end.getTime() - start.getTime(); system.out.println(threadcount + "requests cost" + last + "ms"); }}} catch(ioexception e){e.printstacktrace(); }} / ** *クライアント要求処理スレッドクラス * * @author shieldrn * / class requesthandler runnable {private socket socket; public requesthandler(socket socket){this.socket = socket; } @Override public void run(){try {inputstream in = socket.getInputStream(); //ストリーム:クライアント - >サーバー(読み取り)outputStream out = socket.getOutputStream(); //ストリーム:server-> client(write)int receivebytes; byte [] receivebuffer = new byte [128];文字列clientmessage = ""; if((receivebytes = in.read(receiveBuffer))!= -1){clientMessage = new String(receiveBuffer、0、receiveBytes); if(clientmessage.startswith( "i a a client")){string serverResponseWords = "私はサーバーです。 out.write(serverResponseWords.getBytes()); }} out.flush(); system.out.println( "server:culientmessage->" + clientMessage); } catch(ioexception e){e.printstacktrace(); }}}}}}}}}}この改善された方法により、サーバー処理要求の並行性が向上しますが、各リクエストはスレッドで処理する必要があります。多数の要求により、サーバーは処理のために多数のプロセスを開始します。これは、サーバーリソースも比較的占有されています。
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。