Channel接口定义: http://donald-draper.iteye.com/blog/2369111
AbstractInterruptibleChannel接口定义: http://donald-draper.iteye.com/blog/2369238
SelectableChannel接口定义: http://donald-draper.iteye.com/blog/2369317
SelectionKey定义: http://donald-draper.iteye.com/blog/2369499
SelectorProvider定义: http://donald-draper.iteye.com/blog/2369615
AbstractSelectableChannel定义: http://donald-draper.iteye.com/blog/2369742
NetworkChannel接口定义: http://donald-draper.iteye.com/blog/2369773
ServerSocketChannel定义: http://donald-draper.iteye.com/blog/2369836
ServerSocketChannelImpl解析: http://donald-draper.iteye.com/blog/2370912
Selector定义: http://donald-draper.iteye.com/blog/2370015
AbstractSelector定义: http://donald-draper.iteye.com/blog/2370138
SelectorImpl分析 : http://donald-draper.iteye.com/blog/2370519
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper):
http://donald-draper.iteye.com/blog/2370811
WindowsSelectorImpl解析二(选择操作,通道注册,通道反注册,选择器关闭等):
http://donald-draper.iteye.com/blog/2370862
SocketChannel接口定义: http://donald-draper.iteye.com/blog/2371218
SocketChannelImpl 解析一(通道连接,发送数据): http://donald-draper.iteye.com/blog/2372364
SocketChannelImpl 解析二(发送数据后续): http://donald-draper.iteye.com/blog/2372548
SocketChannelImpl 解析三(接收数据): http://donald-draper.iteye.com/blog/2372590
SocketChannelImpl 解析四(关闭通道等) : http://donald-draper.iteye.com/blog/2372717
MembershipKey定义: http://donald-draper.iteye.com/blog/2372947
MulticastChanne接口定义: http://donald-draper.iteye.com/blog/2373009
MembershipKeyImpl 简介: http://donald-draper.iteye.com/blog/2373066
DatagramChannel定义:http://donald-draper.iteye.com/blog/2373046
DatagramChannelImpl 解析一(初始化): http://donald-draper.iteye.com/blog/2373245
DatagramChannelImpl 解析二(报文发送与接收): http://donald-draper.iteye.com/blog/2373281
DatagramChannelImpl 解析三(多播): http://donald-draper.iteye.com/blog/2373507
DatagramChannelImpl 解析四(地址绑定,关闭通道等): http://donald-draper.iteye.com/blog/2373519
Java Nio从JDK1.4之后,才加入到JDK中,在JDK1.1之后,1.4之前,网络编程一般用阻塞BIO,NIO为非阻的IO,NIO主要包括Selector,Channel(Tcp:ServerSocket,Socket;
Udp:Datagram,File;Pipe:Sink,Source),Buffer,SelectionKey等相关的概念在网上有很多这里就不说了,今天文章我们用NIO写一个基于TCP的简单Server和Client。TCP在NIO主要基于ServerSocketChannel和ServerChannel,下面来看实例。
服务端:
package nio.simplesocket; 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; /** * Sever * @author donald * 2017年4月11日 * 下午9:24:03 */ public class NIOServer { //manager the channel private Selector selector; /** * stat Server * @param args * @throws IOException */ public static void main(String[] args) throws IOException{ NIOServer server = new NIOServer(); server.initServer("192.168.32.126", 10000); server.listen(); } /** * get the ServerSocket and finish some initial work * @param port * @throws IOException */ public void initServer(String host, int port) throws IOException{ //get the ServerSocket ServerSocketChannel serverChannel = ServerSocketChannel.open(); // set no blocking mode serverChannel.configureBlocking(false); //bind the port serverChannel.socket().bind(new InetSocketAddress(host, port)); //get the channel manager this.selector = Selector.open(); //Register the channel to manager and bind the event serverChannel.register(selector,SelectionKey.OP_ACCEPT); } /** * use asking mode to listen the event of selector * @throws IOException */ @SuppressWarnings("rawtypes") public void listen() throws IOException{ System.out.println("=========The Server is start!==========="); while(true){ selector.select(); Iterator ite = this.selector.selectedKeys().iterator(); while(ite.hasNext()){ SelectionKey key = (SelectionKey)ite.next(); ite.remove(); if(key.isAcceptable()){ ServerSocketChannel server = (ServerSocketChannel)key.channel(); SocketChannel channel = server.accept(); channel.configureBlocking(false); channel.write(ByteBuffer.wrap(new String("Hello client!").getBytes())); channel.register(this.selector, SelectionKey.OP_READ); } else if (key.isReadable()) read(key); } } } /** * deal with the message come from the client * @param key * @throws IOException */ public void read(SelectionKey key) throws IOException{ SocketChannel channel = (SocketChannel) key.channel(); ByteBuffer buf = ByteBuffer.allocate(100); channel.read(buf); byte[] data = buf.array(); String msg = new String(data).trim(); System.out.println("message come from client:"+msg); } }
客户端:
package nio.simplesocket; 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.SocketChannel; import java.util.Iterator; /** * Client * @author donald * 2017年4月11日 * 下午9:24:09 */ public class NIOClient { //manager the channel private Selector selector; /** * stat Client * @param args * @throws IOException */ public static void main(String[] args) throws IOException{ NIOClient client = new NIOClient(); client.initClient("192.168.32.126",10000); client.listen(); } /** * get the Socket and finish some initial work * @param ip Server ip * @param port connect Server port * @throws IOException */ public void initClient(String ip,int port) throws IOException{ //get the Socket SocketChannel channel = SocketChannel.open(); // set no blocking mode channel.configureBlocking(false); //connect the Server channel.connect(new InetSocketAddress(ip,port)); //get the channel manager this.selector = Selector.open(); //Register the channel to manager and bind the event channel.register(selector,SelectionKey.OP_CONNECT); } /** * use asking mode to listen the event of selector * @throws IOException */ @SuppressWarnings("rawtypes") public void listen() throws IOException{ System.out.println("===========The Client is start!==========="); while(true){ selector.select(); Iterator ite = this.selector.selectedKeys().iterator(); while(ite.hasNext()){ SelectionKey key = (SelectionKey)ite.next(); ite.remove(); if(key.isConnectable()){ SocketChannel channel = (SocketChannel)key.channel(); //during connecting, finish the connect if(channel.isConnectionPending()){ channel.finishConnect(); } channel.configureBlocking(false); channel.write(ByteBuffer.wrap(new String("Hello Server!").getBytes())); channel.register(this.selector, SelectionKey.OP_READ); } else if (key.isReadable()) read(key); } } } /** * deal with the message come from the server * @param key * @throws IOException */ public void read(SelectionKey key) throws IOException{ SocketChannel channel = (SocketChannel) key.channel(); ByteBuffer buf = ByteBuffer.allocate(100); channel.read(buf); byte[] data = buf.array(); String msg = new String(data).trim(); System.out.println("message come from server:"+msg); } }
先启动NIOServer,在启动NIOClient,控制台输出:
NIOServer:
=========The Server is start!===========
message come from client:Hello Server!
NIOClient:
===========The Client is start!===========
message come from server:Hello client!
附:测试Buffer
package nio; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; /** * 协议测试 * @author donald * 2017年4月10日 * 下午9:26:57 */ public class testByteBuffer { public static void main(String[] args) { ByteBuffer[] proctols = null;// proctols = new ByteBuffer[2]; ByteBuffer protocolBuffer = null;//协议编码 protocolBuffer = ByteBuffer.allocate(6); try { System.out.println("ProtocolCode String length:"+new String("300000").getBytes("UTF-8").length); protocolBuffer.put(new String("300000").getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } System.out.println("ProtocolCode length:"+protocolBuffer.position()); proctols[0] = protocolBuffer; ByteBuffer dataBuffer = null;//操作数 dataBuffer = ByteBuffer.allocate(8); dataBuffer.putInt(15); dataBuffer.putInt(6); System.out.println("data length:"+dataBuffer.position()); proctols[1] = dataBuffer; // protocolBuffer.compact();//针对数据太大,缓冲区一次装不完的情况 protocolBuffer.clear(); try { protocolBuffer.put(new String("300100").getBytes("UTF-8")); System.out.println("ProtocolCode length:"+protocolBuffer.position()); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } // dataBuffer.compact(); dataBuffer.clear(); dataBuffer.putInt(17); dataBuffer.putInt(8); System.out.println("data length:"+dataBuffer.position()); } }