Using NiO for network programming in Java

Source: Internet
Author: User

In JDK, there is a very interesting Library: NiO (New I/O ). This library has three important classes: Selector and channel in Java. NiO. channels and buffer in Java. NiO.

This articleArticleFirst, let's take a look at why NiO is needed for network programming. Then, let's take a look at how to use NiO in network programming step by step.

Why NiO

Socket written in JavaProgramYou must know socket and socketserver. When a call is called, the call is blocked and waits for a response. This method is very convenient for small-scale programs, but it is a little powerless for large programs. When there are a large number of connections, we can create a thread for each connection to operate. However, the defects brought about by this practice are also obvious:

      1. The hardware supports a large amount of concurrency.

      2. There is always an upper limit on the number of concurrent requests.

      3. The priority of each thread is difficult to control.

      4. Interaction and synchronization between clients is difficult.

      We can also use a thread to process all requests and use non-blocking Io to poll and query all clients. This method also has a defect: it cannot quickly respond to the client, and it consumes a lot of time for round-robin queries.

      Therefore, we need a poll mode to deal with this situation and find out the client that really needs services from a large number of network connections. This is exactly why NiO was born: it provides a poll mode to find the client to be served among all the clients.

      Return to the three most important classes we just mentioned: Selector and channel in Java. NiO. channels, and buffer in Java. NiO.

      A channel represents an object that can be used for Poll operations (it can be a file stream or a network stream). A channel can be registered to a selector. By calling the select method of selector, you can find the instance (accept, read...) to be served from all channels ..). The buffer object provides the cache for reading and writing data. Compared with the stream object we are familiar with, buffer provides better performance and better programming transparency (artificially controlling the cache size and specific operations ).

      Use channel with buffer

      It is not used for programming in the traditional mode. The channel does not use stream, but buffer. Let's implement a simple non-blocking echo client:

       Package Com. cnblogs. gpcuster;

      Import Java.net. inetsocketaddress;
      Import Java.net. socketexception;
      Import Java. NiO. bytebuffer;
      Import Java. NiO. channels. socketchannel;

      Public Class Tcpechoclientnonblocking {
      Public Static Void Main (string ARGs []) Throws Exception {
      If (ARGs. Length <2) | (ARGs. length> 3 )) // Testforcorrect # ofargs Throw New Illegalargumentexception (
      " Parameter (s): <Server> <word> [<port>] ");
      String Server = ARGs [0]; // Servernameoripaddress // Convertinputstringtobytesusingthedefacharcharset Byte [] Argument = ARGs [1]. getbytes ();
      Int Servport = (ARGs. Length = 3 )? Integer. parseint (ARGs [2]): 7;
      // Createchannelandsettononblocking Socketchannel clntchan = socketchannel. open (); clntchan. configureblocking ( False );
      // Initiateconnectiontoserverandrepeatedlypolluntilcomplete If (! Clntchan. Connect ( New Inetsocketaddress (server, servport ))){
      While (! Clntchan. finishconnect ()){
      System. Out. Print (" . "); // Dosomethingelse } Bytebuffer writebuf = bytebuffer. Wrap (argument); bytebuffer readbuf = bytebuffer. Allocate (argument. Length ); Int Totalbytesrcvd = 0; // Totalbytesreceivedsofar Int Bytesrcvd; // Bytesreceivedinlastread While (Totalbytesrcvd <argument. Length ){
      If (Writebuf. hasremaining ()){
      Clntchan. Write (writebuf );
      }
      If (Bytesrcvd = clntchan. Read (readbuf) =-1 ){
      Throw New Socketexception (" Connection closed prematurely ");
      }
      Totalbytesrcvd + = bytesrcvd;
      System. Out. Print (" . "); // Dosomethingelse } System. Out. println (" Received: "+// Converttostringperdefacharcharset New String (readbuf. Array (), 0, totalbytesrcvd ));
      Clntchan. Close ();
      }
      }

      This sectionCodeUse bytebuffer to save read and write data. Use clntchan. configureblocking (False); After the setting, the connect, read, and write operations are not blocked, but the result is immediately put back.

      Use Selector

       

       

      Selector can find the desired service instance from all registered channels.

      Let's implement echo server.

      First, define an interface:

      PackageCom. cnblogs. gpcuster;

      ImportJava. NiO. channels. selectionkey;
      ImportJava. Io. ioexception;

      Public InterfaceTcpprotocol {
      VoidHandleaccept (selectionkey key)ThrowsIoexception;

      VoidHandleread (selectionkey key)ThrowsIoexception;

      VoidHandlewrite (selectionkey key)ThrowsIoexception;
      }
       
      Our echo server will use this interface. Then we implement echo server:
       Import Java. Io. ioexception;
      Import Java.net. inetsocketaddress;
      Import Java. NiO. channels. selectionkey;
      Import Java. NiO. channels. selector;
      Import Java. NiO. channels. serversocketchannel;
      Import Java. util. iterator;

      Public Class Tcpserverselector {
      Private Static Final Int Bufsize = 256;// Buffersize (bytes) Private Static Final Int Timeout = 3000; // Waittimeout (milliseconds) Public Static Void Main (string [] ARGs) Throws Ioexception {
      If (ARGs. Length <1 ){ // Testforcorrect # ofargs Throw New Illegalargumentexception (" Parameter (s): <port>... ");
      }
      // Createaselectortomultiplexlisteningsocketsandconnections Selector selector = selector. open (); // Createlisteningsocketchannelforeachportandregisterselector For (String Arg: ARGs ){
      Serversocketchannel listnchannel = serversocketchannel. open ();
      Listnchannel. socket (). BIND (
      New Inetsocketaddress (integer. parseint (ARG )));
      Listnchannel. configureblocking ( False );// Mustbenonblockingtoregister // Registerselectorwithchannel. thereturnedkeyisignored Listnchannel. Register (selector, selectionkey. op_accept );} // Createahandlerthatwilliam mplementtheprotocol Tcpprotocol protocol = New Echoselectorprotocol (bufsize );
      While ( True ){ // Runforever, processingavailablei/oOperations // Waitforsomechanic neltobeready (ortimeout) If (Selector. Select (timeout) = 0 ){// Returns # ofreadychans System. Out. Print (" . ");
      Continue ;
      }
      // Getiteratoronsetofkeyswithi/otoprocess Iterator <selectionkey> keyiter = selector. selectedkeys (). iterator (); While (Keyiter. hasnext ()){
      Selectionkey key = keyiter. Next (); // Keyisbitmask // Serversocketchannelhaspendingconnectionrequests? If (Key. isacceptable ()){
      Protocol. handleaccept (key );
      }
      // Clientsocketchannelhaspendingdata? If (Key. isreadable ()){
      Protocol. handleread (key );
      }
      // Clientsocketchannelisavailableforwritingand // Keyisvalid (I. e., channelnotclosed )? If (Key. isvalid () & Key. iswritable ()){
      Protocol. handlewrite (key );
      }
      Keyiter. Remove (); // Removefromsetofselectedkeys }}}}

      We use listnchannel. register (selector, selectionkey. op_accept); registers an event we are interested in, and then calls selector. select (timeout) waits for the subscription time to occur, and then takes corresponding measures.

      Finally, we implement echoselectorprotocol

       Package Com. cnblogs. gpcuster;

      Import Java. NiO. channels. selectionkey;
      Import Java. NiO. channels. socketchannel;
      Import Java. NiO. channels. serversocketchannel;
      Import Java. NiO. bytebuffer;
      Import Java. Io. ioexception;

      Public Class Echoselectorprotocol Implements Tcpprotocol {
      Private Int Bufsize; // Sizeofi/obuffer Public Echoselectorprotocol ( Int Bufsize ){
      This . Bufsize = bufsize;
      }

      Public Void Handleaccept (selectionkey key) Throws Ioexception {
      Socketchannel clntchan = (serversocketchannel) Key. Channel (). Accept ();
      Clntchan. configureblocking ( False ); // Mustbenonblockingtoregister // Registertheselectorwithnewchannelforreadandattachbytebuffer Clntchan. Register (key. selector (), selectionkey. op_read, bytebuffer. Allocate (bufsize ));} Public Void Handleread (selectionkey key) Throws Ioexception {
      // Clientsocketchannelhaspendingdata Socketchannel clntchan = (socketchannel) Key. Channel (); bytebuffer Buf = (bytebuffer) Key. Attachment (); Long Bytesread = clntchan. Read (BUF );
      If (Bytesread =-1 ){ // Didtheotherendclose? Clntchan. Close ();} Else If (Bytesread> 0 ){
      // Indicateviakeythatreading/writingarebothofinterestnow. Key. interestops (selectionkey. op_read | selectionkey. op_write );}} Public Void Handlewrite (selectionkey key) Throws Ioexception {
      /*
      * Channelisavailableforwriting, andkeyisvalid (I. e., clientchannel
      * Notclosed ).
      */ // Retrievedatareadearlier Bytebuffer Buf = (bytebuffer) Key. Attachment (); Buf. Flip (); // Preparebufferforwriting Socketchannel clntchan = (socketchannel) Key. Channel (); clntchan. Write (BUF ); If (! Buf. hasremaining ()){ // Buffercompletelywritten? // Nothingleft, sonolongerinterestedinwrites Key. interestops (selectionkey. op_read);} Buf. Compact (); // Makeroomformoredatatobereadin }}

      Here, we further register the relevant event for selector: Key. interestops (selectionkey. op_read );

      In this way, we have implemented the NiO-based echo system.

      Reference

      TCP/IP. sockets. In. java.2nd. Edition

      Contact Us

      The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

      If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

      A Free Trial That Lets You Build Big!

      Start building with 50+ products and up to 12 months usage for Elastic Compute Service

      • Sales Support

        1 on 1 presale consultation

      • After-Sales Support

        24/7 Technical Support 6 Free Tickets per Quarter Faster Response

      • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.