NIO的Socket编程

来源:互联网 发布:动漫 知乎 编辑:程序博客网 时间:2024/05/16 06:59
package com.nio;import java.io.IOException;import java.nio.*;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import java.net.*;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", 8888);    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();           for(SelectionKey selectionKey : selectionKeys){                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();        }    }}package com.nio;import java.io.IOException;import java.net.InetSocketAddress;import java.net.ServerSocket;import java.nio.ByteBuffer;import java.nio.CharBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.nio.charset.Charset;import java.nio.charset.CharsetDecoder;import java.util.Iterator;import java.util.LinkedList;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();           for(SelectionKey selectionKey :selectionKeys ){           selectionKeys.remove(selectionKey);               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();    }}