socket-nio

import java.net.InetSocketAddress;
import java.net.Socket;
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.nio.charset.CharsetEncoder;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Properties;
import java.util.Random;

public class SocketDemo {
    public static final int PORT = 13597;

    protected Selector selector;
    protected Charset charset = Charset.forName("UTF-8");
    protected CharsetEncoder charsetEncoder = charset.newEncoder();
    protected CharsetDecoder charsetDecoder = charset.newDecoder();

    protected Properties talks = new Properties();

    int clientCount;
    char b;
    
    public SocketDemo() throws Exception {

    selector = Selector.open();

    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.socket().bind(new InetSocketAddress(PORT)); // port
    serverSocketChannel.configureBlocking(false);
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);// register

    p("Server localhost:" + PORT + " started. waiting for clients. ");

    while (true) {
       // selector 线程。select() 会阻塞,直到有客户端连接,或者有消息读入
       selector.select();
       Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
       while (iterator.hasNext()) {

        SelectionKey selectionKey = iterator.next();
        iterator.remove(); // 删除此消息

        // 并在当前线程内处理。(为了高效,一般会在另一个线程中处理此消息,例如使用线程池等)
        handleSelectionKey(selectionKey);
       }
    }

    }

    public void handleSelectionKey(SelectionKey selectionKey) throws Exception {
        //送出XOR Key
        Random r = new Random();
//        int b = r.nextInt(255)%256;
//        int b = 113;
        
        if (selectionKey.isAcceptable()) {
    
           // 有客户端进来
           clientCount++;
           
           //KEY
//           b = r.nextInt(255)%256;
           b = '0';
           
           ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
           SocketChannel socketChannel = serverSocketChannel.accept();
           socketChannel.configureBlocking(false);
           Socket socket = socketChannel.socket();
    
           // 立即注册一个 OP_READ 的SelectionKey, 接收客户端的消息
           SelectionKey key = socketChannel.register(selector, SelectionKey.OP_READ);
           key.attach(" NO . " + clientCount + " client [" + socket.getRemoteSocketAddress() + "]: ");
    
           p(key.attachment() + "\t[connected] =========================================");
           
           socketChannel.write(charsetEncoder.encode(CharBuffer.wrap("0")));
        } else if (selectionKey.isReadable()) {
            
            System.out.println("KEY  : "+b);
            
           // 有消息进来
    
           ByteBuffer byteBuffer = ByteBuffer.allocate(100);
           SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
           try {
            int len = socketChannel.read(byteBuffer);
            // 如果len>0,表示有输入。如果len==0, 表示输入结束。需要关闭 socketChannel
            if (len > 0) {
    
             byteBuffer.flip();
//             String msg = charsetDecoder.decode(byteBuffer).toString();
             byte[] bte = byteBuffer.array();
             System.out.println(Arrays.toString(bte));
             String s = "";
             for(int i=0; i<bte.length; i++){
                 s += (char)(bte[i]^48);
             }
//             System.out.println(Arrays.toString(bte));
             // 根据客户端的消息,查找到对应的输出
//             ByteBuffer byteBuffer2 = ByteBuffer.allocate(bte.length);
//             byteBuffer2 = byteBuffer2.put(bte);
//             byteBuffer2.flip();
//             String newMsg = charsetDecoder.decode(byteBuffer2).toString();
    //         if (newMsg == null)
    //          newMsg = "Sorry? I don't understand your message. ";
    
             // UTF-8 格式输出到客户端,并输出一个'n'
    
//             socketChannel.write(charsetEncoder.encode(CharBuffer.wrap(newMsg)));
    //         p(selectionKey.attachment() + "\t[recieved]: " + msg + " ----->\t[send]: " + newMsg);
//             p(selectionKey.attachment() + "\t[recieved]: " + msg);
             p(selectionKey.attachment() + "\t[recieved]: " + s);
            } else {
             // 输入结束,关闭 socketChannel
             p(selectionKey.attachment() + "read finished. close socketChannel. ");
             socketChannel.close();
            }
    
           } catch (Exception e) {
    
            // 如果read抛出异常,表示连接异常中断,需要关闭 socketChannel
            e.printStackTrace();
    
            p(selectionKey.attachment() + "socket closed? ");
            socketChannel.close();
           }
    
        } else if (selectionKey.isWritable()) {
           p(selectionKey.attachment() + "TODO: isWritable() ");
        } else if (selectionKey.isConnectable()) {
           p(selectionKey.attachment() + "TODO: isConnectable()  ");
        } else {
           p(selectionKey.attachment() + "TODO: else. ");
        }

    }

    public static void p(Object object) {
        System.out.println(object);
    }

    public static void main(String[] args) throws Exception {
        new SocketDemo();
    }


}

 

posted on 2014-08-07 13:45  Love I Smile  阅读(387)  评论(0编辑  收藏  举报