最近一直在忙着JAVA NIO的知识,花了一下午的时间,总算写出了一个可以运行的程序,废话少说,上代码!
Java代码:
- import java.io.IOException;
- import java.net.InetSocketAddress;
- import java.net.ServerSocket;
- 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;
- import java.util.Set;
- public class NIOServer {
- /*标识数字*/
- private int flag = 0;
- /*缓冲区大小*/
- private int BLOCK = 4096;
- /*接受数据缓冲区*/
- private ByteBuffer sendbuffer = ByteBuffer.allocate(BLOCK);
- /*发送数据缓冲区*/
- private ByteBuffer receivebuffer = ByteBuffer.allocate(BLOCK);
- private Selector selector;
- public NIOServer(int port) throws IOException {
- // 打开服务器套接字通道
- ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
- // 服务器配置为非阻塞
- serverSocketChannel.configureBlocking(false);
- // 检索与此通道关联的服务器套接字
- ServerSocket serverSocket = serverSocketChannel.socket();
- // 进行服务的绑定
- serverSocket.bind(new InetSocketAddress(port));
- // 通过open()方法找到Selector
- selector = Selector.open();
- // 注册到selector,等待连接
- serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
- System.out.println("Server Start----8888:");
- }
- // 监听
- private void listen() throws IOException {
- while (true) {
- // 选择一组键,并且相应的通道已经打开
- selector.select();
- // 返回此选择器的已选择键集。
- Set<SelectionKey> selectionKeys = selector.selectedKeys();
- Iterator<SelectionKey> iterator = selectionKeys.iterator();
- while (iterator.hasNext()) {
- SelectionKey selectionKey = iterator.next();
- iterator.remove();
- handleKey(selectionKey);
- }
- }
- }
- // 处理请求
- private void handleKey(SelectionKey selectionKey) throws IOException {
- // 接受请求
- ServerSocketChannel server = null;
- SocketChannel client = null;
- String receiveText;
- String sendText;
- int count=0;
- // 测试此键的通道是否已准备好接受新的套接字连接。
- if (selectionKey.isAcceptable()) {
- // 返回为之创建此键的通道。
- server = (ServerSocketChannel) selectionKey.channel();
- // 接受到此通道套接字的连接。
- // 此方法返回的套接字通道(如果有)将处于阻塞模式。
- client = server.accept();
- // 配置为非阻塞
- client.configureBlocking(false);
- // 注册到selector,等待连接
- client.register(selector, SelectionKey.OP_READ);
- } else if (selectionKey.isReadable()) {
- // 返回为之创建此键的通道。
- client = (SocketChannel) selectionKey.channel();
- //将缓冲区清空以备下次读取
- receivebuffer.clear();
- //读取服务器发送来的数据到缓冲区中
- count = client.read(receivebuffer);
- if (count > 0) {
- receiveText = new String( receivebuffer.array(),0,count);
- System.out.println("服务器端接受客户端数据--:"+receiveText);
- client.register(selector, SelectionKey.OP_WRITE);
- }
- } else if (selectionKey.isWritable()) {
- //将缓冲区清空以备下次写入
- sendbuffer.clear();
- // 返回为之创建此键的通道。
- client = (SocketChannel) selectionKey.channel();
- sendText="message from server--" + flag++;
- //向缓冲区中输入数据
- sendbuffer.put(sendText.getBytes());
- //将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位
- sendbuffer.flip();
- //输出到通道
- client.write(sendbuffer);
- System.out.println("服务器端向客户端发送数据--:"+sendText);
- client.register(selector, SelectionKey.OP_READ);
- }
- }
- /**
- * @param args
- * @throws IOException
- */
- public static void main(String[] args) throws IOException {
- // TODO Auto-generated method stub
- int port = 8888;
- NIOServer server = new NIOServer(port);
- server.listen();
- }
- }
Java代码:
- 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;
- import java.util.Set;
- public class NIOClient {
- /*标识数字*/
- private static int flag = 0;
- /*缓冲区大小*/
- private static int BLOCK = 4096;
- /*接受数据缓冲区*/
- private static ByteBuffer sendbuffer = ByteBuffer.allocate(BLOCK);
- /*发送数据缓冲区*/
- private static ByteBuffer receivebuffer = ByteBuffer.allocate(BLOCK);
- /*服务器端地址*/
- private final static InetSocketAddress SERVER_ADDRESS = new InetSocketAddress(
- "localhost", 1111);
- public static void main(String[] args) throws IOException {
- // TODO Auto-generated method stub
- // 打开socket通道
- SocketChannel socketChannel = SocketChannel.open();
- // 设置为非阻塞方式
- socketChannel.configureBlocking(false);
- // 打开选择器
- Selector selector = Selector.open();
- // 注册连接服务端socket动作
- socketChannel.register(selector, SelectionKey.OP_CONNECT);
- // 连接
- socketChannel.connect(SERVER_ADDRESS);
- // 分配缓冲区大小内存
- Set<SelectionKey> selectionKeys;
- Iterator<SelectionKey> iterator;
- SelectionKey selectionKey;
- SocketChannel client;
- String receiveText;
- String sendText;
- int count=0;
- while (true) {
- //选择一组键,其相应的通道已为 I/O 操作准备就绪。
- //此方法执行处于阻塞模式的选择操作。
- selector.select();
- //返回此选择器的已选择键集。
- selectionKeys = selector.selectedKeys();
- //System.out.println(selectionKeys.size());
- iterator = selectionKeys.iterator();
- while (iterator.hasNext()) {
- selectionKey = iterator.next();
- if (selectionKey.isConnectable()) {
- System.out.println("client connect");
- client = (SocketChannel) selectionKey.channel();
- // 判断此通道上是否正在进行连接操作。
- // 完成套接字通道的连接过程。
- if (client.isConnectionPending()) {
- client.finishConnect();
- System.out.println("完成连接!");
- sendbuffer.clear();
- sendbuffer.put("Hello,Server".getBytes());
- sendbuffer.flip();
- client.write(sendbuffer);
- }
- client.register(selector, SelectionKey.OP_READ);
- } else if (selectionKey.isReadable()) {
- client = (SocketChannel) selectionKey.channel();
- //将缓冲区清空以备下次读取
- receivebuffer.clear();
- //读取服务器发送来的数据到缓冲区中
- count=client.read(receivebuffer);
- if(count>0){
- receiveText = new String( receivebuffer.array(),0,count);
- System.out.println("客户端接受服务器端数据--:"+receiveText);
- client.register(selector, SelectionKey.OP_WRITE);
- }
- } else if (selectionKey.isWritable()) {
- sendbuffer.clear();
- client = (SocketChannel) selectionKey.channel();
- sendText = "message from client--" + (flag++);
- sendbuffer.put(sendText.getBytes());
- //将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位
- sendbuffer.flip();
- client.write(sendbuffer);
- System.out.println("客户端向服务器端发送数据--:"+sendText);
- client.register(selector, SelectionKey.OP_READ);
- }
- }
- selectionKeys.clear();
- }
- }
- }
个人感觉,JAVA NIO的操作时麻烦了不少,但是无疑这样做效率会得到很大的提升。
原文链接:http://xm-king.iteye.com/blog/766330
【编辑推荐】