基于Selector+Channel+线程池的server & client

来源:互联网 发布:禁止网络标语 编辑:程序博客网 时间:2024/06/10 21:11

server:

package com.tang.selector;import java.io.IOException;import java.net.InetSocketAddress;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;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ExecutorService;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;/** * Created by TangXW on 2017/8/11. */public class TimeServer {    private static ExecutorService executor;    static{        executor = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1000));    }    public static void main(String[] args) throws IOException{        ServerSocketChannel ssc = ServerSocketChannel.open();        ssc.socket().bind(new InetSocketAddress(8080));        ssc.configureBlocking(false);        Selector selector = Selector.open();        ssc.register(selector, ssc.validOps());        while(true){            // 如果不设置连接超时,那么这个方法一直是阻塞的            int readCount = selector.select(1000);            if(readCount == 0){                continue;            }            Set<SelectionKey> selectionKeySets = selector.selectedKeys();            Iterator<SelectionKey> keyIterator = selectionKeySets.iterator();            while(keyIterator.hasNext()){                SelectionKey selectionKey = keyIterator.next();                if(selectionKey.isValid()){  // 此键是否有效                    // 表示是serversocketchannel                    if(selectionKey.isAcceptable()){                        ServerSocketChannel server = (ServerSocketChannel) selectionKey.channel();                        SocketChannel socketChannel = server.accept();                        socketChannel.configureBlocking(false);                        socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);                    }                    // 表示SocketChannel                    if(selectionKey.isReadable()){                        executor.submit(new TimeServerTask(selectionKey));                    }                    keyIterator.remove();                }            }        }    }}

servertask:

package com.tang.selector;import java.io.IOException;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.SocketChannel;import java.util.Calendar;/** * Created by TangXW on 2017/8/11. */public class TimeServerTask implements Runnable{    private SelectionKey selectionKey;    public TimeServerTask(SelectionKey selectionKey){        this.selectionKey = selectionKey;    }    @Override    public void run() {        SocketChannel channel = (SocketChannel) selectionKey.channel();        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);        try{            int count = 0;            // 如果从socketchannel中有数据            while((count = channel.read(byteBuffer)) > 0){                byteBuffer.flip();                byte[] request = new byte[byteBuffer.remaining()];                byteBuffer.get(request);                String requestStr = new String(request);                byteBuffer.clear();                if(!"GET CURRENT TIME".equals(requestStr)){                    channel.write(byteBuffer.put("BAD_REQUEST".getBytes()));                }else{                    // 写入当前的时间戳                    byteBuffer.put(Calendar.getInstance().getTime().toLocaleString().getBytes());                    byteBuffer.flip();                    channel.write(byteBuffer);                }            }        } catch (IOException e){            e.printStackTrace();            selectionKey.cancel();        }    }}

client:

package com.test.nio;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SocketChannel;/** * Created by TangXW on 2017/8/11. */public class TimeClient2 {    //连接超时时间    static int connectTimeOut = 3000;    static ByteBuffer buffer = ByteBuffer.allocateDirect(1024);    public static void main(String[] args) throws IOException, InterruptedException {        SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(8080));        socketChannel.configureBlocking(false);        long start = System.currentTimeMillis();        while (!socketChannel.finishConnect()){            if (System.currentTimeMillis() - start >= connectTimeOut){                throw new RuntimeException("尝试建立连接超过3秒");            }        }        // 如果走到这一步,说明连接建立成功        while (true){            buffer.put("GET CURRENT TIME".getBytes());            buffer.flip();            socketChannel.write(buffer);            buffer.clear();  // 清空然后将传过来的数据重新写入            if(socketChannel.read(buffer) > 0){                buffer.flip();                byte[] response = new byte[buffer.remaining()];                buffer.get(response);                System.out.println("reveive response:" + new String(response));                buffer.clear();            }            Thread.sleep(5000);        }    }}

output:

reveive response:2017-8-14 13:33:31reveive response:2017-8-14 13:33:36reveive response:2017-8-14 13:33:41reveive response:2017-8-14 13:33:46reveive response:2017-8-14 13:33:51...
原创粉丝点击