Java NiO instance

Source: Internet
Author: User

We all know that TCP is a connection-oriented transport layer protocol. A socket must be bound to a connection. In a common bio (blocking Io), three handshakes are required, then the General socket programming is like this.

The socket server process is as follows: Load socket> Create a socket for listening> bind socket> listen socket> process client-related requests.

The Socket Client also needs to load the socket first and then create the socket, but then it does not need to bind and listen, but directly connects to the server and sends related requests.

 

They keep occupying this connection. If information is sent, they will respond. Otherwise, they will be blocked. If there are multiple connections, you need to use multiple threads to process one connection. When there are few connections, it is allowed. However, if too many connections are processed simultaneously, for example, 1000, then we will encounter a bottleneck on the win platform. If it is 2000, we will encounter a bottleneck on Linux, because the number of threads that each process can create on different platforms is limited, in addition, too many threads will inevitably cause the system to schedule the thread more efficiently. How can we ensure that the thread takes precedence over the queue and blocks the queue? For example, if there are one thousand threads, the minimum stack size of a thread is 1 MB, memory is also a huge consumption.

In short, the blocking Io is:One connection <one by one> one thread
.

 

Now NiO appears. java. NiO package and Java new I/O are introduced in java1.4. Introduces common buffer and channel concepts in the operating system.

 

Buffer zone:In the operating system, the buffer is used to solve the problem that the CPU computing speed does not match the peripheral input/output speed, because the peripherals are too slow. If there is no buffer, when the CPU enters the peripherals, it will wait until the CPU processing efficiency is low. After the buffer is introduced, the peripherals directly put the data in the buffer. After the data transmission is complete, give the CPU an interrupt signal and notify the CPU: "If my data has been transferred, you can fetch it from the buffer ". The same is true for output.

Channel:So what is the channel used? In fact, it can be seen from his name that it is a channel. The data you want to pass out is placed in the buffer zone. How can you transfer the data from the buffer zone? Or how can peripherals transmit data to the buffer? Channels are used here. It can further reduce CPU intervention and improve the resource utilization of the entire system more efficiently. For example, when the CPU needs to complete a set of related read operations, you only need to send a command to the I/O channel to give the first address of the channel program to be executed and the device to be accessed, the tunnel program can complete the I/O tasks specified by the CPU.

Selector:Another innovation is the selector. When we use a channel, the channel may not be ready, or there may be new requests, or the thread may be blocked, the selector can help the CPU understand this information, provided that the channel is registered with this selector.

 

 

The following example shows a very relevant example:

A bus from A to B may get off at many points on the road. The driver does not know which persons will get off the bus. What should they do better?

1. The driver regularly asks if each passenger has arrived at the destination. If someone says so, the driver stops and gets off the bus. (Similar to blocking)

2. Each person tells the conductor his destination and goes to bed. The driver only interacts with the conductor. At a certain point, the conductor notifies the passengers to get off the bus. (Similar to non-blocking)

Obviously, each person who wants to reach a destination can be considered as a thread, and the driver can think of it as a CPU. In the blocking mode, each thread needs to continuously poll and switch the context to locate the destination. In the non-blocking mode, every passenger (thread) is sleeping (sleep) and wakes up only when the real external environment is ready. Such a wake-up will certainly not be blocked.

 

 

What is implemented in non-blocking Io is:One request <one by one> one thread

 

In the following example, a thread is used to listen to two serversockets, which can be processed only when the request is sent.

Server

 

Package CN. vicky. channel; 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. NIO. channels. SPI. selectorprovider; import Java. util. iterator;/*** NiO of TCP/IP non-blocking mode * server side **/public class server impleme CNT runnable {// The first port private integer port1 = 8099; // The second port private integer port2 = 9099; // The first server channel service a private serversocketchannel serversocket1; // second server channel service B private serversocketchannel serversocket2; // connect 1 private socketchannel clientchannel1; // connect 2 Private socketchannel clientchannel2; // selector, it is mainly used to monitor the event private selector of each channel; // buffer private bytebuffer Buf = bytebuffer. allocate (1, 512); P Ublic server () {Init ();}/*** function of this method * 1: initialization selector * 2: open two channels * 3: bind a socket * 4 to the channel: register the selector to the channel **/Public void Init () {try {// create the selector this. selector = selectorprovider. provider (). openselector (); // open the first server channel this. serversocket1 = serversocketchannel. open (); // tell the program that the current method is not blocking this. serversocket1.configureblocking (false); // obtain the socket currently associated with this channel. serversocket1.socket (). BIND (New inetsocketaddress ("Lo Calhost ", this. port1); // register the selector to the channel and return an operation set bit // op_accept used by the socket to accept the operation. This. serversocket1.register (this. selector, selectionkey. op_accept); // then initialize the second server this. serversocket2 = serversocketchannel. open (); this. serversocket2.configureblocking (false); this. serversocket2.socket (). BIND (New inetsocketaddress ("localhost", this. port2); this. serversocket2.register (this. selector, selectionkey. op_accept);} c Atch (exception e) {e. printstacktrace () ;}}/*** this method is used to connect * client to the server * @ throws ioexception **/Public void accept (selectionkey key) throws ioexception {serversocketchannel Server = (serversocketchannel) Key. channel (); If (server. equals (serversocket1) {clientchannel1 = server. accept (); clientchannel1.configureblocking (false); // op_read the operation set bit clientchannel1.register (this. selector, selecti Onkey. op_read);} else {clientchannel2 = server. accept (); clientchannel2.configureblocking (false); // The number of clientchannel2.register (this. selector, selectionkey. op_read) ;}}/*** read data from the channel * and judge the * @ throws ioexception **/Public void read (selectionkey key) for the service channel) throws ioexception {This. buf. clear (); // select the key to find the previously registered channel // but here the registered serversocketchannel returns a socketchannel ?? Socketchannel channel = (socketchannel) Key. channel (); // read data from the channel to the buffer and return the number of read bytes int COUNT = channel. read (this. buf); If (COUNT =-1) {// cancel the registration key for this channel. channel (). close (); key. cancel (); return;} // extract data from the buffer string input = new string (this. buf. array ()). trim (); // now it is determined that the service is connected if (channel. equals (this. clientchannel1) {system. out. println ("Welcome to service a"); system. out. println ("your input is:" + input);} else {SY Stem. out. println ("Welcome to service B"); system. out. println ("your input is:" + input) ;}@ override public void run () {While (true) {try {system. out. println ("running... "); // select a group of keys, and the corresponding channel is ready for the I/O operation. This. selector. select (); // return the selected key set of this selector // public abstract set <selectionkey> selectedkeys () iterator selectorkeys = This. selector. selectedkeys (). iterator (); While (selectorkeys. hasnext () {system. out. println ("running2... "); // locate the current selectionkey key = (selectionkey) selectorkeys. next (); // then delete selectorkeys from the return key queue. remove (); If (! Key. isvalid () {// The selection key is invalid. Continue;} If (key. isacceptable () {// returns this if a request is received. accept (key);} else if (key. isreadable () {// read client data this. read (key) ;}} catch (exception e) {e. printstacktrace () ;}} public static void main (string [] ARGs) {server Server = new server (); thread = new thread (server); thread. start ();}}

Client

Package CN. vicky. channel; import Java. io. ioexception; import java.net. inetsocketaddress; import Java. NIO. bytebuffer; import Java. NIO. channels. socketchannel; import java.net. inetaddress;/*** NiO non-blocking mode of TCP/IP * client **/public class client {// create a buffer private bytebuffer buffer = bytebuffer. allocate (512); // Access Server public void query (string host, int port) throws ioexception {inetsocketaddress address = new ine Tsocketaddress (inetaddress. getbyname (host), Port); socketchannel socket = NULL; byte [] bytes = new byte [512]; while (true) {try {system. in. read (bytes); socket = socketchannel. open (); socket. connect (Address); buffer. clear (); buffer. put (bytes); buffer. flip (); socket. write (buffer); buffer. clear ();} catch (exception e) {e. printstacktrace ();} finally {If (socket! = NULL) {socket. close () ;}}} public static void main (string [] ARGs) throws ioexception {new client (). query ("localhost", 8099 );}}

 

The preceding server listens to two services in one thread, and the entire server has only one blocking method:

// Select a group of keys, and the corresponding channel is ready for I/O operations.

This. selector. Select ();

 

When the customer requests the server, this creates the illusion that TCP does not have connection orientation. In fact, it is connected at least when data is transmitted, after an I/O request is completed, the server disconnects and continues to process more requests. On the client side, you can see that the server is connected once when a request is encountered. Therefore, TCP is connection-oriented.

Now I know why non-blocking I/O is used.

 

 

 

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.