一个NIO服务器、客户端通信示例

来源:互联网 发布:西西软件下载网站 编辑:程序博客网 时间:2024/05/23 12:03

服务器端代码:

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.ArrayList;import java.util.Iterator;import java.util.List;/** * 服务器端demo */public class Server {    public static void main(String[] args) {        new Server().start();    }    public void start(){        ServerSocketChannel ssc = null;        Selector selector;        try {            ssc = ServerSocketChannel.open();            ssc.configureBlocking(false);            ssc.socket().bind(new InetSocketAddress(8899));            selector = Selector.open();            ssc.register(selector, SelectionKey.OP_ACCEPT);            System.out.println("服务器启动完成,正在监听。。。");            while (true) {                selector.select();                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();                while (iterator.hasNext()) {                    SelectionKey key = iterator.next();                    if(key.isAcceptable()){                        ServerSocketChannel _ssc = (ServerSocketChannel) key.channel();                        SocketChannel sc = _ssc.accept();                        sc.configureBlocking(false);                        sc.register(selector , SelectionKey.OP_READ);                        System.out.printf("监听到客户端连接,ip:%s,端口:%s\n" , sc.socket().getInetAddress().getHostAddress() , sc.socket().getPort());                    }else if(key.isReadable()){                        SocketChannel sc = (SocketChannel) key.channel();                        ByteBuffer buffer = ByteBuffer.allocate(1024);                        List<Byte> list = new ArrayList<>();                        try {                            while (sc.read(buffer) > 0){//从套接字通道读取客户端发过来的数据直到读取完                                buffer.flip();//ByteBuffer从写模式切换到读模式                                while (buffer.hasRemaining()){                                    list.add(buffer.get());                                }                                buffer.clear();//清空缓冲区,为下一次循环读取数据腾出空间                            }                            if(list.isEmpty()){//如果收到客户端消息是空的                                System.out.println("客户端断开。。。");                                sc.close();                            }else{                                byte[] bytes = new byte[list.size()];                                for(int i = 0 ; i < bytes.length ; ++i){                                    bytes[i] = list.get(i);                                }                                String str = new String(bytes);                                System.out.println("from client:" + str);                                ByteBuffer bf = ByteBuffer.wrap(bytes);//把客户端发过来的这条消息原样发回给客户端                                sc.write(bf);                            }                        } catch (IOException e) {                            e.printStackTrace();                            sc.close();                        }                    }                    iterator.remove();//这里一定要把key移除                }            }        } catch (IOException e) {            e.printStackTrace();        } finally {            if (ssc != null) {                try {                    ssc.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}



客户端代码:

import java.io.BufferedReader;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStreamReader;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;/** * 客户端demo */public class Client {    private SocketChannel sc = null;    private Selector selector = null;    private ByteArrayOutputStream baos = null;    public static void main(String[] args) {        new Client().start();    }    public void start(){        ByteBuffer buffer = null;        try {            baos = new ByteArrayOutputStream();            selector = Selector.open();            buffer = ByteBuffer.allocate(1024);            sc = SocketChannel.open();            sc.configureBlocking(false);            //这里只注册了SelectionKey.OP_READ,只关心是否能读取服务器消息            sc.register(selector , SelectionKey.OP_READ);            sc.connect(new InetSocketAddress("127.0.0.1" , 8899));            //等待100毫秒直到连接上服务器            while (!sc.finishConnect()){                try {                    Thread.sleep(100);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }            //新线程处理控制台输入            new Thread(new InputThread(sc)).start();            while (true){                selector.select();                if(selector == null || !selector.isOpen())                    break;                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();                while (iterator.hasNext()){                    SelectionKey key = iterator.next();                    if(key.isReadable()){                        while (sc.read(buffer) > 0){                            int position = buffer.position();                            buffer.flip();                            baos.write(buffer.array() , 0 , position);                            buffer.clear();                        }                        if(baos.size() > 0){                            System.out.println("from server:" + new String(baos.toByteArray()));                            baos.reset();                        }                    }                    iterator.remove();                }            }        } catch (IOException e) {            e.printStackTrace();        }    }    private class InputThread implements Runnable{        SocketChannel sc = null;        private InputThread(SocketChannel sc) {            this.sc = sc;        }        @Override        public void run() {            System.out.println("客户端准备就绪,快输入消息发送给服务器吧");            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));            while (true){                try {                    String line = reader.readLine();                    if(line == null || line.length() == 0){                        sc.close();                        selector.close();                        baos.close();                        break;                    }                    sc.write(ByteBuffer.wrap(line.getBytes()));                } catch (IOException e) {                    e.printStackTrace();                    break;                }            }        }    }}



运行结果:



0 0