Java nio socket communication instance Program

Source: Internet
Author: User

Nio is short for java New IO. It is a New api provided in jdk1.4. The following is a small compilation to help you sort out a socket communication instance program for nio in java, let's take a look at it with me.

Although the Java platform has a lot of pretty good step-by-step socket frameworks, such as Netty and naga, we should be aware of it.

Nio is short for java New IO. The New api provided by jdk1.4 has the following features officially advertised by Sun:

Provide Buffer cache support for all original types
Character Set encoding and decoding solution
Channel: A new original I/O Abstraction
Supports file access interfaces for lock and memory ing files
Provides non-bloking (non-bloking) non-blocking high-scalability network I/O
Basic Principles

NIO has a main class Selector. This is similar to an observer. As long as we tell the Selector about the SocketChannel to be explored, we will continue to do other things. When an event occurs, it will notify us, return a group of selectionkeys. When we read these keys, we will obtain the SocketChannel we just registered. Then, we will read data from this Channel, so we can rest assured that the package will be able to read, then we can process the data.

The internal principle of Selector is actually to make a round-robin access to the registered channel and continuously round-robin (this algorithm currently). Once a channel is registered, for example, when the data comes, he will stand up and report, hand over a key, and let us read the contents of this channel through this key.


The code written based on nio is a bit cool, so it is better to write it with a framework. The functions implemented by this server are relatively simple, but only the data sent from the client is returned.

Server

Initialize Selector

The Code is as follows: Copy code

Private Selector initSelector () throws IOException {
Selector socketSelector = SelectorProvider. provider (). openSelector ();
This. serverChannel = ServerSocketChannel. open ();
ServerChannel. configureBlocking (false );
InetSocketAddress isa = new InetSocketAddress (this. hostAddress, this. port );
ServerChannel. socket (). bind (isa );
ServerChannel. register (socketSelector, SelectionKey. OP_ACCEPT );
 
Return socketSelector;
}

Accept incoming connections

The Code is as follows: Copy code

Private void accept (SelectionKey key) throws IOException {
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key. channel ();
SocketChannel socketChannel = serverSocketChannel. accept ();
Socket socket = socketChannel. socket ();
SocketChannel. configureBlocking (false );
SocketChannel. register (this. selector, SelectionKey. OP_READ );
LOGGER.info ("ACCEPT:" + socket. getInetAddress (). toString ());
}

Accept data

The Code is as follows: Copy code

Private void read (SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key. channel ();
This. readBuffer. clear ();
Int numRead;
Try {
NumRead = socketChannel. read (this. readBuffer );
} Catch (IOException e ){
Key. cancel ();
SocketChannel. close ();
Return;
}
 
If (numRead =-1 ){
Key. channel (). close ();
Key. cancel ();
Return;
}
 
// Hand the data off to our worker thread
This. worker. processData (this, socketChannel, this. readBuffer. array (), numRead );
}

Send data

The Code is as follows: Copy code

Private void write (SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key. channel ();
List <ByteBuffer> queue = this. pendingData. get (socketChannel );
 
While (! Queue. isEmpty ()){
ByteBuffer buf = queue. get (0 );
SocketChannel. write (buf );
If (buf. remaining ()> 0 ){
Break;
}
Queue. remove (0 );
}
 
If (queue. isEmpty ()){
Key. interestOps (SelectionKey. OP_READ );
}
}

Client

Client Initialization is quite simple

The Code is as follows: Copy code

Private Selector initSelector () throws IOException {
Return SelectorProvider. provider (). openSelector ();
}

Accept data

The Code is as follows: Copy code

Private void read (SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key. channel ();
This. readBuffer. clear ();
 
Int numRead;
Try {
NumRead = socketChannel. read (this. readBuffer );
} Catch (IOException e ){
Key. cancel ();
SocketChannel. close ();
Return;
}
 
If (numRead =-1 ){
Key. channel (). close ();
Key. cancel ();
Return;
}
 
// Handle the response
This. handleResponse (socketChannel, this. readBuffer. array (), numRead );
}

Send data

The Code is as follows: Copy code

Private void write (SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key. channel ();
List <ByteBuffer> queue = this. pendingData. get (socketChannel );
 
While (! Queue. isEmpty ()){
ByteBuffer buf = queue. get (0 );
SocketChannel. write (buf );
If (buf. remaining ()> 0 ){
Break;
}
Queue. remove (0 );
}
 
If (queue. isEmpty ()){
Key. interestOps (SelectionKey. OP_READ );
}
}

Auxiliary class

EchoWorker is responsible for sending the received client data back. Your specific business logic can be achieved through a similar method.

The Code is as follows: Copy code
Import java. nio. channels. SocketChannel;
Import java. util. concurrent. BlockingQueue;
Import java. util. concurrent. Define blockingqueue;
 
Public class EchoWorker implements Runnable {
Private BlockingQueue <ServerDataEvent> queue = new LinkedBlockingQueue <ServerDataEvent> ();
 
Public void processData (NioServer, SocketChannel socket, byte [] data, int count ){
Byte [] dataCopy = new byte [count];
System. arraycopy (data, 0, dataCopy, 0, count );
Try {
Queue. put (new ServerDataEvent (server, socket, dataCopy ));
} Catch (InterruptedException e ){
E. printStackTrace ();
}
}
 
Public void run (){
 
While (true ){
Try {
ServerDataEvent dataEvent = queue. take ();
// Return to sender
DataEvent. server. send (dataEvent. socket, dataEvent. data );
} Catch (InterruptedException e ){
E. printStackTrace ();
}
}
}
}

ChangeRequest is responsible for processing the SocketChannel status

The Code is as follows: Copy code

Import java. nio. channels. SocketChannel;
 
Public class ChangeRequest {
Public static final int REGISTER = 1;
Public static final int CHANGEOPS = 2;
 
Public SocketChannel socket;
Public int type;
Public int ops;
 
Public ChangeRequest (SocketChannel socket, int type, int ops ){
This. socket = socket;
This. type = type;
This. ops = ops;
}
}

RspHandler is responsible for processing client data. In actual cases, you can process your own business logic in this class.

The Code is as follows: Copy code

Public class RspHandler {
Private byte [] rsp = null;
 
Public synchronized boolean handleResponse (byte [] rsp ){
This. rsp = rsp;
This. Policy ();
Return true;
}
 
Public synchronized void waitForResponse (){
While (this. rsp = null ){
Try {
This. wait ();
} Catch (InterruptedException e ){
}
}
 
System. out. println ("process message:" + new String (this. rsp ));
}
}

Start

The Code is as follows: Copy code

// Start the client
Public static void main (String [] args) throws UnknownHostException, IOException {
For (int I = 0; I <10; I ++ ){
Try {
NioClient client = new NioClient (InetAddress. getLocalHost (), 9090 );
Thread t = new Thread (client );
T. setDaemon (true );
T. start ();
RspHandler handler = new RspHandler ();
Client. send ("test message" + I + 10). getBytes (), handler );
Handler. waitForResponse ();
} Catch (Exception e ){
E. printStackTrace ();
}
}
}
 
// Start the server
Public static void main (String [] args ){
Try {
EchoWorker worker = new EchoWorker ();
New Thread (worker). start ();
New Thread (new NioServer (null, 9090, worker). start ();
} Catch (IOException e ){
E. printStackTrace ();
}
}

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.