Java NIO Study Notes
The project team is engaged in IM products, and the server certainly uses NIO technology as the communication bottom layer. However, I have always been familiar with some NIO theories and have no practice. Now I am free to practice NIO.
NIO, new IO, also known as non-blocking IO. Non-blocking is one of the most important differences between non-blocking and traditional IO. Traditional IO uses Socket for communication, while NIO uses channel for message interaction. The channel must be registered on the selector to notify the selector of the events it is interested in. This is an implementation of the observer mode. This describes the relationship between the channel and selector. The channel is a train track, and the selector is a train dispatching room. Multiple channels can be registered to the same selector and scheduled in one thread. However, traditional IO needs to create a thread for each socket. This is also one of NIO's advantages and does not require too many threads.
Server code of NIO version:
Package cn. nio; 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; public class NioServer {private SelectorserverSelector; public NioServer initServer (int port) throws IOException {Ser VerSocketChannel serverChannel = ServerSocketChannel. open (); // non-blocking mode serverChannel. configureBlocking (false); // bind the port number to serverChannel. socket (). bind (new InetSocketAddress (port); this. serverSelector = Selector. open (); serverChannel. register (serverSelector, SelectionKey. OP_ACCEPT); return this;} public void startListening () throws IOException {System. out. println ("server started successfully! "); While (true) {// The method returns when the registered event arrives; otherwise, the method will always block serverSelector. select (); Iterator
Iterator = this. serverSelector. selectedKeys (). iterator (); while (iterator. hasNext () {SelectionKey key = (SelectionKey) iterator. next (); // It must be deleted; otherwise, the old keyiterator will be traversed next time. remove (); if (key. isAcceptable () {accept (key);} else if (key. isReadable () {read (key) ;}}// accept client connection request private void accept (SelectionKey key) throws IOException {ServerSocketChannel server = (ServerSocketChannel) key. channel (); // obtain the channel SocketChannel connected to the client = server. accept (); // set to non-blocking channel. configureBlocking (false); channel. write (ByteBuffer. wrap (new String ("client connection successful \ n "). getBytes (); // register a channel. register (this. serverSelector, SelectionKey. OP_READ);} private void read (SelectionKey key) {try {SocketChannel channel = (SocketChannel) key. channel (); // create the read buffer ByteBuffer buffer = ByteBuffer. allocate (1, 1024); channel. read (buffer); String msg = new String (buffer. array ()). trim (); System. out. println ("server:" + msg);} catch (Exception e) {e. printStackTrace () ;}} public static void main (String [] args) throws IOException {new NioServer (). initServer (8080 ). startListening ();}}
Client code of NIO version:
Package cn. nio; import java. io. IOException; import java.net. inetSocketAddress; import java. nio. byteBuffer; import java. nio. channels. closedChannelException; import java. nio. channels. selectionKey; import java. nio. channels. selector; import java. nio. channels. socketChannel; import java. util. iterator; public class NioClient {private Selectorselector; public NioClient initClient (String ip, int port) throws IOExcept Ion {SocketChannel channel = SocketChannel. open (); // non-blocking channel. configureBlocking (false); this. selector = Selector. open (); // Note of the connect Method: This method returns false, and the connection operation must be completed by calling the finishConnect method later. Boolean result = channel. connect (new InetSocketAddress (ip, port); System. out. println (result); // return false // register the channel. register (selector, SelectionKey. OP_CONNECT); return this;} public void startListening () throws IOException {while (true) {selector. select (); Iterator
Iterator = this. selector. selectedKeys (). iterator (); while (iterator. hasNext () {SelectionKey key = (SelectionKey) iterator. next (); // It must be deleted; otherwise, the old keyiterator will be traversed next time. remove (); if (key. isConnectable () {connect (key);} else if (key. isReadable () {read (key) ;}}} private void connect (SelectionKey key) throws IOException, ClosedChannelException {SocketChannel channel = (SocketChannel) key. channel (); // if the connection is in progress, the connection if (channel. isConnectionPending () {channel. finishConnect ();} channel. configureBlocking (false); channel. write (ByteBuffer. wrap (new String ("client connection successful "). getBytes (); // register a channel. register (this. selector, SelectionKey. OP_READ);} private void read (SelectionKey key) throws IOException {// the server can read the message: Obtain the Socket channel SocketChannel channel = (SocketChannel) key of the event. channel (); // create the read buffer ByteBuffer buffer = ByteBuffer. allocate (1, 1024); channel. read (buffer); String msg = new String (buffer. array ()). trim (); System. out. println ("message received by the Client:" + msg);}/*** start the client test ** @ throws IOException */public static void main (String [] args) throws IOException {new NioClient (). initClient ("localhost", 8080 ). startListening ();}}
Considering that NIO technology is not necessarily available in other languages, our clients are C ++. Can a NIO server communicate with a non-NIO client? A traditional I/O client is used for testing. Feasible!
Package cn. nio; import java. io. bufferedReader; import java. io. IOException; import java. io. inputStreamReader; import java. io. printWriter; import java.net. socket; public class NormalClient {SocketclientSocket = null; public NormalClient initClient (String ip, int port) {try {clientSocket = new Socket (ip, port);} catch (IOException e) {e. printStackTrace ();} return this;} public void read () throws IOException {PrintWriter pw = new PrintWriter (clientSocket. getOutputStream (); BufferedReader br = new BufferedReader (new InputStreamReader (clientSocket. getInputStream (); String line = null; while (true) {pw. println ("messages sent from the client"); pw. flush (); line = br. readLine (); System. out. println (line) ;}} public static void main (String [] args) throws IOException {new NormalClient (). initClient ("127.0.0.1", 8000 ). read ();}}