Bio, yaitu, memblokir IO. Selama proses komunikasi pesan berbasis soket, server soket menyediakan layanan ke luar, dan klien soket dapat membuat koneksi ke server soket, kemudian mengirim data permintaan, kemudian menunggu server soket untuk diproses, dan mengembalikan hasil pemrosesan (respons).
Berdasarkan komunikasi bio, server soket akan memblokir, yaitu, setiap kali koneksi soket ke klien diterima selama proses mendengarkan, permintaan harus diproses, dan pada saat ini, klien lain yang terhubung hanya dapat memblokir dan menunggu. Dapat dilihat bahwa kemampuan pemrosesan server soket dalam mode ini sangat terbatas, dan klien hanya dapat menunggu sampai server menganggur dan menangani permintaan.
Implementasi Komunikasi Bio
Berikut ini didasarkan pada model BIO untuk mengimplementasikan logika server soket sederhana yang berkomunikasi dengan klien soket, dan memiliki pemahaman persepsi tentang metode komunikasi ini. Logika spesifik digambarkan sebagai berikut:
1. Klien Socket terhubung ke server soket dan mengirimkan data "Saya klien N.";
2. Server Socket mendengarkan port layanan dan menerima data permintaan klien. Jika data permintaan dimulai dengan "Saya klien", itu merespons klien "Saya server, dan Anda adalah klien ke -n.";
Implementasi server soket adalah sebagai berikut:
paket org.shirdrn.java.communications.bio; impor java.io.ioException; impor java.io.inputstream; impor java.io.outputStream; impor java.net.serversocket; impor java.net.socket; / *** Socket Server berbasis di bio** @author shieldrn*/ kelas publik SimpleBiotCpserver memperluas utas {/ ** Nomor port layanan*/ port int private = 8888; / ** Tetapkan nomor*/ int private static ke urutan klien = 0; publik SimpleBiotCpserver (int port) {this.port = port; } @Override public void run () {socket socket = null; Coba {ServerSocket ServerSocket = New ServerSocket (this.port); while (true) {socket = serversocket.accept (); // dengarkan ini.handlemessage (socket); // handlemessage (soket); // menangani permintaan klien yang terhubung}} catch (ioException e) {e.printstacktrace (); }} / ** * Tangani koneksi soket klien * @param soket klien soket * @throws ioException * / private void handlemessage (soket soket) melempar ioException {inputStream in = socket.getInputStream (); // stream: client-> server (baca) outputStream out = socket.getoutputStream (); // stream: server-> client (write) int recequedbytes; byte [] recreepBuffer = byte baru [128]; String clientMessage = ""; if ((receptBytes = in.read (recequentBuffer))! =-1) {clientMessage = string baru (recequingBuffer, 0, recequentbytes); if (clientmessage.startswith ("I Am the Client")) {String serverResponseWords = "I Am The Server, dan Anda adalah" ++ Urutan) + "Klien."; out.write (serverResponsewords.getbytes ()); }} out.flush (); System.out.println ("Server: menerima ClientMessage->" + ClientMessage); } public static void main (string [] args) {SimpleBiotCpserver server = new SimpleBiotCpserver (1983); server.start (); }} Implementasi di atas tidak melakukan pemrosesan pengecualian yang kompleks.
Implementasi klien soket adalah sebagai berikut:
paket org.shirdrn.java.communications.bio; impor java.io.ioException; impor java.io.inputstream; impor java.io.outputStream; impor java.net.socket; impor java.net.unknownhostException; impor java.util.date; / ** * klien soket berdasarkan bio * * @author shieldrn */ kelas publik SimpleBiotCpClient {private string ipaddress; port int pribadi; Private static int pos = 0; Public SimpleBiotCpClient () {} public SimpleBiotCpClient (String ipaddress, int port) {this.ipaddress = ipaddress; this.port = port; } / *** Sambungkan ke server soket dan simulasikan data permintaan pengiriman* @param data permintaan data* / public void kirim (byte [] data) {socket socket = null; OutputStream out = null; Inputstream in = null; coba {socket = soket baru (this.ipaddress, this.port); // Connect // Kirim permintaan out = socket.getoutputStream (); out.write (data); out.flush (); // menerima respons di = socket.getInputStream (); int totalbytes = 0; int recequedbytes = 0; byte [] recreepBuffer = byte baru [128]; if ((receptBytes = in.read (recequentBuffer))! =-1) {totalBytes += recequentbytes; } String servermessage = string baru (recequingbuffer, 0, recequentbytes); System.out.println ("Client: menerima servermessage->" + servermessage); } catch (unknownHostException e) {e.printstacktrace (); } catch (ioException e) {e.printstacktrace (); } catch (Exception e) {E.PrintStackTrace (); } akhirnya {coba {// kirim permintaan dan terima respons, komunikasi selesai, tutup koneksi out.close (); melampirkan(); socket.close (); } catch (ioException e) {e.printstacktrace (); }}} public static void main (string [] args) {int n = 1; Data StringBuffer = StringBuffer baru (); Tanggal mulai = tanggal baru (); untuk (int i = 0; i <n; i ++) {data.delete (0, data.length ()); Data.Append ("I Am The Client") .Append (++ POS) .Append ("."); SimpleBiotCpClient Client = new SimpleBiotCpClient ("LocalHost", 1983); client.send (data.toString (). getBytes ()); } Tanggal akhir = tanggal baru (); biaya panjang = end.getTime () - start.getTime (); System.out.println (n + "permintaan biaya" + biaya + "ms."); }} Pertama mulai proses server soket SimpleBiotCpserver, dan kemudian jalankan klien soket SimpleBiotCpClient. Dapat dilihat bahwa server menerima data permintaan dan kemudian menanggapi klien, dan klien menerima data respons dari server.
Dalam implementasi di atas, baik klien soket dan server ditulis dan dibacakan sekaligus. Pada kenyataannya, jika jumlah data sangat besar selama setiap komunikasi, server tidak dapat menerimanya. Dapat mengulang untuk membaca dan memprosesnya saat menentukan jumlah byte data yang diminta oleh klien.
Selain itu, jika aliran yang disebutkan di atas tidak dibungkus, akan ada kerugian kinerja dalam praktiknya, seperti ketidakmampuan untuk buffer, dll.
Untuk data yang menerima server soket, jauh lebih nyaman jika data byte dibaca dari beberapa loop dapat disimpan melalui buffer byte panjang variabel. Namun, menggunakan bytearrayoutputStream, misalnya:
BytearrayoutputStream data = bytearrayoutputStream () baru; Data.write (ReceCTBuffer, TotalBytes, TotalBytes + ReceCTYTES);
Tes Komunikasi Bio
Berikut menguji efisiensi pemrosesan server soket dalam skenario dengan sejumlah besar permintaan.
Metode pertama: Mulai 5000 klien soket melalui loop for dan kirim permintaan. Kodenya adalah sebagai berikut:
public static void main (string [] args) {int n = 5000; Data StringBuffer = StringBuffer baru (); Tanggal mulai = tanggal baru (); untuk (int i = 0; i <n; i ++) {data.delete (0, data.length ()); Data.Append ("I Am The Client") .Append (++ POS) .Append ("."); SimpleBiotCpClient Client = new SimpleBiotCpClient ("LocalHost", 1983); client.send (data.toString (). getBytes ()); } Tanggal akhir = tanggal baru (); biaya panjang = end.getTime () - start.getTime (); System.out.println (n + "permintaan biaya" + biaya + "ms."); } Setelah pengujian, dibutuhkan sekitar 9864ms, yaitu sekitar 10 -an.
Metode kedua: Mulai 5.000 utas klien independen dan permintaan pada saat yang sama, dan server diperhitungkan:
paket org.shirdrn.java.communications.bio; impor java.io.ioException; impor java.io.inputstream; impor java.io.outputStream; impor java.net.serversocket; impor java.net.socket; impor java.net.unknownhostException; impor java.util.date; / ** * Tes Komunikasi Soket Berdasarkan Bio * * @Author Shieldrn */ Kelas Publik SimpleBiotCPtest {static int threadCount = 5000; / *** Socket Server Proses Berdasarkan Bio** @Author Shieldrn*/ Socketserver kelas statis memperluas utas {/ ** Nomor port layanan*/ port int private = 8888; / ** Tetapkan nomor ke klien*/ urutan int statis privat = 0; Public SocketServer (int port) {this.port = port; } @Override public void run () {socket socket = null; int counter = 0; Coba {ServerSocket ServerSocket = New ServerSocket (this.port); bendera boolean = false; Tanggal mulai = null; while (true) {socket = serversocket.accept (); // dengarkan // Waktu dimulai jika (! Bendera) {start = new date (); bendera = true; } this.handlemessage (socket); // menangani permintaan klien yang terhubung jika (++ counter == threadCount) {date end = new date (); Long last = end.getTime () - start.getTime (); System.out.println (threadCount + "permintaan biaya" + terakhir + "ms."); }}}} catch (ioException e) {e.printstacktrace (); }} / ** * Tangani koneksi soket klien * @param soket klien soket * @throws ioException * / private void handlemessage (soket soket) melempar ioException {inputStream in = socket.getInputStream (); // stream: client-> server (baca) outputStream out = socket.getoutputStream (); // stream: server-> client (write) int recequedbytes; byte [] recreepBuffer = byte baru [128]; String clientMessage = ""; if ((receptBytes = in.read (recequentBuffer))! =-1) {clientMessage = string baru (recequingBuffer, 0, recequentbytes); if (clientmessage.startswith ("I Am the Client")) {String serverResponseWords = "I Am The Server, dan Anda adalah" ++ Urutan) + "Klien."; out.write (serverResponsewords.getbytes ()); }} out.flush (); System.out.println ("Server: menerima ClientMessage->" + ClientMessage); }} / ** * utas klien soket berdasarkan bio * * @author shieldrn * / kelas statis socketclient mengimplementasikan runnable {private string ipaddress; port int pribadi; / ** Meminta data untuk dikirim*/ data string pribadi; socketclient publik (string ipaddress, int port) {this.ipaddress = ipaddress; this.port = port; } @Override public void run () {this.send (); } / *** Sambungkan ke server soket dan simulasikan data permintaan pengiriman* / public void send () {socket socket = null; OutputStream out = null; Inputstream in = null; coba {socket = soket baru (this.ipaddress, this.port); // Connect // Kirim permintaan keluar = socket.getoutputStream (); out.write (data.getbytes ()); out.flush (); // menerima respons di = socket.getInputStream (); int totalbytes = 0; int recequedbytes = 0; byte [] recreepBuffer = byte baru [128]; if ((receptBytes = in.read (recequentBuffer))! =-1) {totalBytes += recequentbytes; } String servermessage = string baru (recequingbuffer, 0, recequentbytes); System.out.println ("Client: menerima servermessage->" + servermessage); } catch (unknownHostException e) {e.printstacktrace (); } catch (ioException e) {e.printstacktrace (); } catch (Exception e) {E.PrintStackTrace (); } akhirnya {coba {// kirim permintaan dan terima respons, komunikasi selesai, tutup koneksi out.close (); melampirkan(); socket.close (); } catch (ioException e) {e.printstacktrace (); }}} public void setData (string data) {this.data = data; }} public static void main (string [] args) melempar Exception {SocketServer server = SocketServer baru (1983); server.start (); Thread.sleep (3000); untuk (int i = 0; i <threadCount; i ++) {socketclient client = socketclient baru ("localhost", 1983); client.setData ("Saya klien" + (i + 1) + "."); utas baru (klien) .start (); Thread.sleep (0, 1); }}}Setelah pengujian, dibutuhkan sekitar 7110ms, yaitu sekitar 7s, dan tidak ada peningkatan besar.
Perbaikan Komunikasi Bio
Melalui tes di atas, kami dapat menemukan bahwa ketika server soket memproses permintaan dari klien, terjadi pemblokiran, yang secara serius mempengaruhi efisiensi pemrosesan permintaan secara bersamaan. Bahkan, dalam ruang lingkup kemampuan koneksi server soket, permintaan yang diterima dapat independen, sehingga dapat menyelesaikan masalah di atas dengan memproses permintaan dengan satu permintaan dan satu utas. Dengan cara ini, sisi server memiliki banyak utas pemrosesan yang sesuai dengan banyak permintaan klien, dan efisiensi pemrosesan telah ditingkatkan sampai batas tertentu.
Di bawah ini, terima permintaan melalui satu utas, dan kemudian mendelegasikan kumpulan utas untuk melakukan permintaan pemrosesan bersamaan multi-threaded:
/ *** Socket Server Proses Berdasarkan Bio** @Author Shieldrn*/ Socketserver kelas statis memperluas utas {/ ** Nomor port layanan*/ port int private = 8888; / ** Tetapkan nomor ke klien*/ urutan int statis privat = 0; / ** kumpulan utas untuk memproses permintaan klien*/ pool executorservice pribadi; socketserver publik (int port, int poolsize) {this.port = port; this.pool = executors.newfixedThreadpool (poolsize); } @Override public void run () {socket socket = null; int counter = 0; Coba {ServerSocket ServerSocket = New ServerSocket (this.port); bendera boolean = false; Tanggal mulai = null; while (true) {socket = serversocket.accept (); // dengarkan // Waktu dimulai jika suatu permintaan datang jika (! Bendera) {start = new date (); bendera = true; } // Masukkan permintaan klien ke dalam kumpulan utas untuk memproses pool.execute (new requesthandler (soket)); if (++ counter == threadCount) {date end = new date (); Long last = end.getTime () - start.getTime (); System.out.println (threadCount + "permintaan biaya" + terakhir + "ms."); }}} catch (ioException e) {E.PrintStackTrace (); }} / ** * Kelas pemrosesan Permintaan klien Kelas utas * * @Author Shieldrn * / kelas requestHandler mengimplementasikan runnable {soket soket pribadi; public revandHandler (soket soket) {this.socket = socket; } @Override public void run () {coba {inputStream in = socket.getInputStream (); // stream: client-> server (baca) outputStream out = socket.getoutputStream (); // stream: server-> client (write) int recequedbytes; byte [] recreepBuffer = byte baru [128]; String clientMessage = ""; if ((receptBytes = in.read (recequentBuffer))! =-1) {clientMessage = string baru (recequingBuffer, 0, recequentbytes); if (clientmessage.startswith ("I Am the Client")) {String serverResponseWords = "I Am The Server, dan Anda adalah" ++ Urutan) + "Klien."; out.write (serverResponsewords.getbytes ()); }} out.flush (); System.out.println ("Server: menerima ClientMessage->" + ClientMessage); } catch (ioException e) {e.printstacktrace (); }}}}}}}}}Dapat dilihat bahwa metode yang ditingkatkan ini meningkatkan konkurensi permintaan pemrosesan server, tetapi setiap permintaan harus diproses oleh utas. Sejumlah besar permintaan menyebabkan server memulai sejumlah besar proses untuk diproses, yang juga relatif menempati sumber daya server.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.