In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
This article focuses on "the difference between traditional IO and NIO". Interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn the difference between traditional IO and NIO.
Let's first look at a piece of traditional IO code.
Public class OioServer {public static void main (String [] args) throws IOException {/ / here can be directly written as ServerSocket server = new ServerSocket (10101); ServerSocket server = new ServerSocket (); server.bind (new InetSocketAddress (10101)); System.out.println ("server startup"); while (true) {/ / here Socket socket = server.accept () System.out.println ("A new client is coming"); handler (socket);}} public static void handler (Socket socket) {try {byte [] bytes = new byte [1024]; InputStream inputStream = socket.getInputStream (); while (true) {int read = inputStream.read (bytes) If (read! =-1) {System.out.println (new String (bytes,0,read));} else {break;} catch (IOException e) {e.printStackTrace ();} finally {try {System.out.println ("socket off") Socket.close ();} catch (IOException e) {e.printStackTrace ();}
Connect using telnet
AdmindeMacBook-Pro:~ admin$ telnet 127.0.0.1 10101
Trying 127.0.0.1...
Connected to localhost.
Escape character is'^]'.
We will see the operation of OioServer
Server startup
There's a new client.
But when we use another telnet connection, the operation of OioServer remains the same, indicating that a server can only receive one client endpoint connection because Socket socket = server.accept (); there is a blockage, and now we rewrite it to multithreading
Public class OioServerThread {public static void main (String [] args) throws IOException {ServerSocket server = new ServerSocket (10101); ExecutorService service = Executors.newFixedThreadPool (Runtime.getRuntime (). AvailableProcessors () * 2); System.out.println ("server startup"); while (true) {Socket socket = server.accept (); System.out.println ("here's a new client") Service.execute (()-> handler (socket));}} public static void handler (Socket socket) {try {byte [] bytes = new byte [1024]; InputStream inputStream = socket.getInputStream (); while (true) {int read = inputStream.read (bytes) If (read! =-1) {System.out.println (new String (bytes,0,read));} else {break;} catch (IOException e) {e.printStackTrace ();} finally {try {System.out.println ("socket off") Socket.close ();} catch (IOException e) {e.printStackTrace ();}
Running shows that when we start multiple telnet to connect, it can be connected together
Server startup
There's a new client.
There's a new client.
But there is a problem here. The available threads in our thread pool are limited. It is impossible to provide a thread indefinitely to receive a large number of client connections. Sooner or later, it will be blocked without response.
Now let's take a look at the fact that NIO,NIO uses the features of traditional IO to create a channel (channel) through which event SelectionKey is registered.
There are four events in SelectionKey
SelectionKey.OP_ACCEPT-receive connection resume event, indicating that the server is listening to the client connection and the server can receive the connection
SelectionKey.OP_CONNECT-connection ready event, indicating that the connection between the client and the server has been established successfully
SelectionKey.OP_READ-read ready event, indicating that the channel has readable data and is ready to perform a read operation (the channel currently has data and can be read)
SelectionKey.OP_WRITE-write ready event, indicating that data can be written to the channel (the channel is currently available for write operations)
Note here, the following two kinds, SelectionKey.OP_READ, SelectionKey.OP_WRITE
1. When the SelectionKey.OP_READ event is registered with the channel, if the client has write data in the cache, the next poll will isReadable () = true
two。 When you register the SelectionKey.OP_WRITE event with the channel, you will find that isWritable () is always ture in the current polling thread, if it is not set to another event
Public class NIOServer {/ / Channel manager private Selector selector; / * get a ServerSocket channel and do some initialization work on the channel * * @ param port * bound port number * @ throws IOException * / public void initServer (int port) throws IOException {/ / get a ServerSocket channel ServerSocketChannel serverChannel = ServerSocketChannel.open () / / set the channel to non-blocking serverChannel.configureBlocking (false); / / bind the ServerSocket corresponding to the channel to the port port serverChannel.socket () .bind (new InetSocketAddress (port)); / / get a channel manager this.selector = Selector.open () / / bind the channel manager to the channel and register the SelectionKey.OP_ACCEPT event for the channel. After registering the event, / / when the event arrives, selector.select () will return, and will block if the event does not reach selector.select (). ServerChannel.register (selector, SelectionKey.OP_ACCEPT);} / * uses polling to listen for events on the selector that need to be handled, and if so, deal with * * @ throws IOException * / public void listen () throws IOException {System.out.println ("server started successfully!") ; / / Poll access selector while (true) {/ / when the registered event arrives, the method returns Otherwise, the method will always block selector.select (); / / get the iterator of the selected item in selector, and the selected item is the registered event Iterator ite = this.selector.selectedKeys (). Iterator (); while (ite.hasNext ()) {SelectionKey key = (SelectionKey) ite.next () / / Delete the selected key to prevent repeated processing of ite.remove (); handler (key) } / * process request * * @ param key * @ throws IOException * / public void handler (SelectionKey key) throws IOException {/ / client request connection event if (key.isAcceptable ()) {handlerAccept (key) / / got a readable event} else if (key.isReadable ()) {handelerRead (key);}} / * handle connection requests * * @ param key * @ throws IOException * / public void handlerAccept (SelectionKey key) throws IOException {ServerSocketChannel server = (ServerSocketChannel) key.channel () / / get the channel to connect with the client SocketChannel channel = server.accept (); / / set to non-blocking channel.configureBlocking (false); / / you can send information to the client here, oh System.out.println ("new client connection") / / after a successful connection with the client, in order to receive the information from the client, you need to set the read permission to the channel. Channel.register (this.selector, SelectionKey.OP_READ);} / * * handle read events * * @ param key * @ throws IOException * / public void handelerRead (SelectionKey key) throws IOException {/ / Server readable messages: get the Socket channel SocketChannel channel = (SocketChannel) key.channel () / / create read buffer ByteBuffer buffer = ByteBuffer.allocate (1024); int read = channel.read (buffer); if (read > 0) {byte [] data = buffer.array (); String msg = new String (data). Trim (); System.out.println ("Server receives message:" + msg) / / write back data ByteBuffer outBuffer = ByteBuffer.wrap ("OK" .getBytes ()); channel.write (outBuffer); / / send the message back to the client} else {System.out.println ("client shutdown"); key.cancel () Start server test * * @ throws IOException * / public static void main (String [] args) throws IOException {NIOServer server = new NIOServer (); server.initServer (10101); server.listen ();}}
The biggest difference between NIO and traditional IO
NIO has the concept of channel, which is not found in traditional IO, but the concept of channel is based on traditional IO.
Traditional IO character acceptance processing is also a practical way to serialize streams native to Java, while NIO uses ByteBuffer's buffer mechanism.
Using telnet testing, NIO definitely supports multiple clients to operate at the same time, but it is important that NIO is single-threaded. The logic of traditional IO and NIO is as follows
Traditional IO
NIO
As for how NIO multithreaded, you can refer to how NIO multithreaded operation, which is actually the principle of Netty.
Connect with two telnet respectively
AdmindeMacBook-Pro:IOServer admin$ telnet 127.0.0.1 10101
Trying 127.0.0.1...
Connected to localhost.
Escape character is'^]'.
Dsfds
Yes
AdmindeMacBook-Pro:~ admin$ telnet 127.0.0.1 10101
Trying 127.0.0.1...
Connected to localhost.
Escape character is'^]'.
22222
Yes
The server is displayed as follows
Server started successfully!
New client connection
The server receives the message: dsfds
New client connection
The server receives a message: 22222
When we quit one of them,
AdmindeMacBook-Pro:~ admin$ telnet 127.0.0.1 10101
Trying 127.0.0.1...
Connected to localhost.
Escape character is'^]'.
22222
Okay ^]
Telnet > quit
Connection closed.
The server is displayed as follows
Server started successfully!
New client connection
The server receives the message: dsfds
New client connection
The server receives a message: 22222
Client shutdown
If we close shell directly after we connect using telnet, the server will throw an exception
Server started successfully!
New client connection
The server receives a message:
Exception in thread "main" java.io.IOException: Connection reset by peer
At sun.nio.ch.FileDispatcherImpl.read0 (Native Method)
At sun.nio.ch.SocketDispatcher.read (SocketDispatcher.java:39)
At sun.nio.ch.IOUtil.readIntoNativeBuffer (IOUtil.java:223)
At sun.nio.ch.IOUtil.read (IOUtil.java:197)
At sun.nio.ch.SocketChannelImpl.read (SocketChannelImpl.java:380)
At com.guanjian.websocket.io.NIOServer.handelerRead (NIOServer.java:111)
At com.guanjian.websocket.io.NIOServer.handler (NIOServer.java:77)
At com.guanjian.websocket.io.NIOServer.listen (NIOServer.java:59)
At com.guanjian.websocket.io.NIOServer.main (NIOServer.java:134)
Indicates that an exception was thrown when reading the Buffer buffer, so we should catch the exception while reading instead of throwing it
/ * * handle read events * * @ param key * @ throws IOException * / public void handelerRead (SelectionKey key) {/ / Server readable messages: get the Socket channel where the event occurred SocketChannel channel = (SocketChannel) key.channel (); / / create a read buffer ByteBuffer buffer = ByteBuffer.allocate (1024); try {int read = channel.read (buffer) If (read > 0) {byte [] data = buffer.array (); String msg = new String (data). Trim (); System.out.println ("Server receives message:" + msg); / / write back data ByteBuffer outBuffer = ByteBuffer.wrap ("OK" .getBytes ()); channel.write (outBuffer) / / send the message back to the client} else {System.out.println (client shutdown); key.cancel ();}} catch (IOException e) {e.printStackTrace ();}}
Let's now prove that NIO is single-threaded and modify the above code
/ * * handle read events * * @ param key * @ throws IOException * / public void handelerRead (SelectionKey key) {/ / server readable messages: get the Socket channel where the event occurred SocketChannel channel = (SocketChannel) key.channel (); / / create a read buffer ByteBuffer buffer = ByteBuffer.allocate (1024); try {int read = channel.read (buffer); Thread.sleep (60000) If (read > 0) {byte [] data = buffer.array (); String msg = new String (data). Trim (); System.out.println ("Server receives message:" + msg); / / write back data ByteBuffer outBuffer = ByteBuffer.wrap ("OK" .getBytes ()); channel.write (outBuffer) / / send the message back to the client} else {System.out.println (client shutdown); key.cancel ();}} catch (Exception e) {e.printStackTrace ();}}
We asked him to sleep for a minute when he sent the message. Start the server, connect the first telnet, and send a few characters
At this point, when we connect to the second telnet, we will find that the server does not respond. It will take a minute for the first telnet to receive a "good", and the server will display a "new client connection".
Indicates that the server is blocked when processing sending characters, and the NIO is single-threaded.
At this point, I believe you have a deeper understanding of "the difference between traditional IO and NIO". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.