Java NIO (إدخال / إخراج بدون حظر) مع مثال عميل الخادم - java.nio.ByteBuffer والقنوات.Selector - Java NIO مقابل. IO
نشرت: 2021-08-06
Java NIO
هو موضوعي المفضل. أعمل مع NIO منذ العامين الماضيين وأرغب في مشاركة Server-Client code
البسيط لقرائي الذين يتمتعون بحرية استخدام هذا الرمز في بيئة الإنتاج الخاصة بهم.
بدءًا من JDK 1.4 ، تم إنشاء NIO للسماح لجميع مبرمجي Java بتنفيذ إدخال / إخراج عالي السرعة دون الحاجة إلى التعامل مع التعليمات البرمجية الأصلية المخصصة. يستخدم NIO مكتبة java.nio.buffer
مقارنة بمدخلات الإدخال / الإخراج البسيطة التي تستنزف وتعبئ المخزن المؤقت داخليًا لأي نظام تشغيل.
في هذا البرنامج التعليمي سوف ننتقل إلى مكتبات java.nio.channels
و java.nio.channels.Selector
.
- تمثل
channels
الاتصالات بالكيانات القادرة على تنفيذ عمليات الإدخال / الإخراج ، مثل الملفات والمآخذ ؛ يحدد المحددات لعمليات الإدخال / الإخراج متعددة الإرسال وغير المحظورة. - يمكن إنشاء
selector
عن طريق استدعاءopen method
لهذه الفئة ، والتي ستستخدم موفر المحدِّد الافتراضي للنظام لإنشاء محدِّد جديد.

إذا كانت لديك below questions
، فأنت في المكان الصحيح:
- كيف تبدأ مع Java NIO
- ما هي برامج Java NIO و Java NIO التعليمية
- Java NIO غير المتزامن
- ما هو الاستخدام الدقيق لحزمة java nio
- برنامج Java NIO التعليمي
- كيفية تنفيذ إدخال / إخراج عالي الأداء باستخدام Java NIO
هيا بنا نبدأ:
الخطوة 1
- قم
CrunchifyNIOServer.java
الذي يفتح الاتصال علىport 1111
- استخدم
isAcceptable()
للتحقق مما إذا كانت القناة جاهزة لقبول اتصال مقبس جديد- إذا كانت الإجابة بنعم - قم بتوصيله
- استخدم
isReadable()
للتحقق مما إذا كانت القناة جاهزة للقراءة- إذا كانت الإجابة بنعم - اقرأ من المخزن المؤقت واطبع على وحدة تحكم Eclipse
- بمجرد الحصول على اسم الشركة الأخير "crunchify"
- اغلق الاتصال
الخطوة 2
- قم
CrunchifyNIOClient.java
الذي يحاول الاتصال بالخادم علىport 1111
- قم بإنشاء ArrayList مع 5 أسماء شركات
- كرر من خلال ArrayList وأرسل اسم الشركة إلى الخادم
- إغلاق الاتصال بعد انتهاء المهمة
ألق نظرة على كود Java هذا:
كود الخادم - CrunchifyNIOServer.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
package crunchify . com . tutorials ; import java . io . IOException ; import java . net . InetSocketAddress ; import java . nio . ByteBuffer ; import java . nio . channels . SelectionKey ; import java . nio . channels . Selector ; import java . nio . channels . ServerSocketChannel ; import java . nio . channels . SocketChannel ; import java . util . Iterator ; import java . util . Set ; /** * @author Crunchify.com * Java NIO (Non-blocking I/O) with Server-Client Example - java.nio.ByteBuffer and channels.Selector * This is CrunchifyNIOServer.java */ public class CrunchifyNIOServer { @ SuppressWarnings ( "unused" ) public static void main ( String [ ] args ) throws IOException { // Selector: A multiplexor of SelectableChannel objects. // A selector may be created by invoking the open method of this class, which will use the system's default selector provider to create a new selector. // A selector may also be created by invoking the openSelector method of a custom selector provider. A selector remains open until it is closed via its close method. Selector selector = Selector . open ( ) ; // selector is open here // ServerSocketChannel: A selectable channel for stream-oriented listening sockets. // A server-socket channel is created by invoking the open method of this class. // It is not possible to create a channel for an arbitrary, pre-existing ServerSocket. ServerSocketChannel crunchifySocket = ServerSocketChannel . open ( ) ; // InetSocketAddress: This class implements an IP Socket Address (IP address + port number) It can also be a pair (hostname + port number), // in which case an attempt will be made to resolve the hostname. // If resolution fails then the address is said to be unresolved but can still be used on some circumstances like connecting through a proxy. InetSocketAddress crunchifyAddr = new InetSocketAddress ( "localhost" , 1111 ) ; // Binds the channel's socket to a local address and configures the socket to listen for connections crunchifySocket . bind ( crunchifyAddr ) ; // Adjusts this channel's blocking mode. crunchifySocket . configureBlocking ( false ) ; int ops = crunchifySocket . validOps ( ) ; // SelectionKey: A token representing the registration of a SelectableChannel with a Selector. // A selection key is created each time a channel is registered with a selector. // A key remains valid until it is cancelled by invoking its cancel method, by closing its channel, or by closing its selector. SelectionKey selectKy = crunchifySocket . register ( selector , ops , null ) ; // Infinite loop.. // Keep server running while ( true ) { log ( "I'm a server and I'm waiting for new connection and buffer select..." ) ; // Selects a set of keys whose corresponding channels are ready for I/O operations selector . select ( ) ; // token representing the registration of a SelectableChannel with a Selector Set < SelectionKey > crunchifyKeys = selector . selectedKeys ( ) ; Iterator < SelectionKey > crunchifyIterator = crunchifyKeys . iterator ( ) ; while ( crunchifyIterator . hasNext ( ) ) { SelectionKey myKey = crunchifyIterator . next ( ) ; // Tests whether this key's channel is ready to accept a new socket connection if ( myKey . isAcceptable ( ) ) { SocketChannel crunchifyClient = crunchifySocket . accept ( ) ; // Adjusts this channel's blocking mode to false crunchifyClient . configureBlocking ( false ) ; // Operation-set bit for read operations crunchifyClient . register ( selector , SelectionKey . OP_READ ) ; log ( "Connection Accepted: " + crunchifyClient . getLocalAddress ( ) + "\n" ) ; // Tests whether this key's channel is ready for reading } else if ( myKey . isReadable ( ) ) { SocketChannel crunchifyClient = ( SocketChannel ) myKey . channel ( ) ; // ByteBuffer: A byte buffer. // This class defines six categories of operations upon byte buffers: // Absolute and relative get and put methods that read and write single bytes; // Absolute and relative bulk get methods that transfer contiguous sequences of bytes from this buffer into an array; ByteBuffer crunchifyBuffer = ByteBuffer . allocate ( 256 ) ; crunchifyClient . read ( crunchifyBuffer ) ; String result = new String ( crunchifyBuffer . array ( ) ) . trim ( ) ; log ( "Message received: " + result ) ; if ( result . equals ( "Crunchify.com" ) ) { crunchifyClient . close ( ) ; log ( "\nIt's time to close connection as we got last company name 'Crunchify'" ) ; log ( "\nServer will keep running. Try running client again to establish new connection" ) ; } } crunchifyIterator . remove ( ) ; } } } private static void log ( String str ) { System . out . println ( str ) ; } } |
كود العميل - CrunchifyNIOClient.java

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
package crunchify . com . tutorials ; import java . io . IOException ; import java . net . InetSocketAddress ; import java . nio . ByteBuffer ; import java . nio . channels . SocketChannel ; import java . util . ArrayList ; /** * @author Crunchify.com * Java NIO (Non-blocking I/O) with Server-Client Example - java.nio.ByteBuffer and channels.Selector * This is CrunchifyNIOClient.java */ public class CrunchifyNIOClient { public static void main ( String [ ] args ) throws IOException , InterruptedException { InetSocketAddress crunchifyAddr = new InetSocketAddress ( "localhost" , 1111 ) ; // selectable channel for stream-oriented connecting sockets SocketChannel crunchifyClient = SocketChannel . open ( crunchifyAddr ) ; log ( "Connecting to Server on port 1111..." ) ; ArrayList <String> companyDetails = new ArrayList <String> ( ) ; // create a ArrayList with companyName list companyDetails . add ( "Facebook" ) ; companyDetails . add ( "Twitter" ) ; companyDetails . add ( "IBM" ) ; companyDetails . add ( "Google" ) ; companyDetails . add ( "Crunchify" ) ; for ( String companyName : companyDetails ) { byte [ ] message = new String ( companyName ) . getBytes ( ) ; ByteBuffer buffer = ByteBuffer . wrap ( message ) ; crunchifyClient . write ( buffer ) ; log ( "sending: " + companyName ) ; buffer . clear ( ) ; // wait for 2 seconds before sending next message Thread . sleep ( 2000 ) ; } // close(): Closes this channel. // If the channel has already been closed then this method returns immediately. // Otherwise it marks the channel as closed and then invokes the implCloseChannel method in order to complete the close operation. crunchifyClient . close ( ) ; } private static void log ( String str ) { System . out . println ( str ) ; } } |
النتيجة على جانب الخادم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
I 'm a server and I' m waiting for new connection and buffer select . . . Connection Accepted : / 127.0.0.1 : 1111 I 'm a server and <meta charset="utf-8"/>I' m waiting for new connection and buffer select . . . Message received : Facebook < meta charset = "utf-8" / > I 'm a server and <meta charset="utf-8"/>I' m waiting for new connection and buffer select . . . Message received : Twitter < meta charset = "utf-8" / > I 'm a server and <meta charset="utf-8"/>I' m waiting for new connection and buffer select . . . Message received : IBM < meta charset = "utf-8" / > I 'm a server and <meta charset="utf-8"/>I' m waiting for new connection and < a href = "https://crunchify.com/how-to-remove-duplicate-elements-from-csv-or-any-other-file-in-java/" target = "_blank" rel = "noreferrer noopener" > buffer < / a > select . . . Message received : Google < meta charset = "utf-8" / > I 'm a server and <meta charset="utf-8"/>I' m waiting for new connection and buffer select . . . Message received : Crunchify It 's time to <a href="https://crunchify.com/json-manipulation-in-java-examples/" target="_blank" rel="noreferrer noopener">close connection</a> as we got last company name ' Crunchify ' Server will keep running. Try running client again to establish new connection <meta charset="utf-8"/>I' m a server and < meta charset = "utf-8" / > I ' m waiting for new connection and buffer select . . . |
النتيجة من جانب العميل:
1 2 3 4 5 6 |
Connecting to Server on port 1111... sending : Facebook sending : Twitter sending : IBM sending : Google sending : Crunchify |
قليل من الأسئلة الشائعة:
- من العميل ، كيف أحافظ على اتصال دائم؟
- يمكنك استخدام
socket.setKeepAlive(true);
للحصول على اتصالات حية من جانب العميل.
- يمكنك استخدام
- كيف أقرأ ردًا على الرسالة التي أرسلها إلى الخادم. يستمر الخادم في إنشاء الرسائل كل 10 ثوانٍ. أنا فقط بحاجة لقراءة الرد على طلبي. بناءً على ما أفهمه ، فإن بيانات "تدفقات" TCP بدلاً من نهاية السجل ، إلخ.
- بالنسبة لاتصال خادم العميل ، يجب تحديد البروتوكول جيدًا. سيتم حظر مكالمة
readLine()
حتى يتم إرجاع جميع البيانات ، لذلك لا تستخدمها.Try reading bytes from the stream until -1 is returned.
- بالنسبة لاتصال خادم العميل ، يجب تحديد البروتوكول جيدًا. سيتم حظر مكالمة
دعنا نذهب للعمل.
