利用NIO构造简单的聊天功能

来源:互联网 发布:上海好的java培训机构 编辑:程序博客网 时间:2024/05/01 07:33


public class SocketSelector {private final static int PORT = 1234;public static void main(String[] args) throws IOException {new SocketSelector().init(args);}public void init(String... args) throws IOException{int port = PORT;if (args.length != 0) {port = Integer.parseInt(args[0]);}Selector selector = Selector.open();ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.configureBlocking(false);serverSocketChannel.socket().bind(new InetSocketAddress(port));System.out.println("1111");serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("wille to cycle..");while(true){int n = selector.select();if (n == 0) {continue;}<span style="white-space:pre"></span>System.out.println(n);Iterator it = selector.selectedKeys().iterator();while(it.hasNext()){SelectionKey selectionKey = (SelectionKey) it.next();it.remove();//如果去掉这句话,在acceptable里,sayhello函数里socketchannel会是个null值。我猜测每个key只能使用一次System.out.println(selectionKey.interestOps());if(selectionKey.isAcceptable()){ServerSocketChannel serverSocketChannel2 = (ServerSocketChannel) selectionKey.channel();System.out.println(selectionKey.interestOps());SocketChannel socketChannel = serverSocketChannel2.accept();registerChannel(selector,socketChannel,SelectionKey.OP_READ);sayHello(socketChannel);}if(selectionKey.isReadable()){//System.out.println("有读的来了");readDataFromChannel(selectionKey);}}}}private ByteBuffer buf = ByteBuffer.allocate(1024);protected void readDataFromChannel(SelectionKey selectionKey) throws IOException {SocketChannel socketChannel = (SocketChannel) selectionKey.channel();buf.clear();//buf.flip();取消注释,单个客户端发送一条数据,服务器端就无限死循环,输出“1 1 有读的来了”;第一个1为int n的值,第二个1是key.interestOps的值,1代表Readableint count = 0;while((count=socketChannel.read(buf))>0){System.out.println("count:"+count+",buf.size:"+buf.position());//while(buf.hasRemaining()){System.out.println("hasRemaining:"+buf.hasRemaining()+",buf.size:"+buf.position());byte[] data = buf.array();String str = new String(data);System.out.println(str);//}buf.clear();}if (count < 0) {
<span style="white-space:pre">System.out.println("close the channel...");</span>socketChannel.close();}}private void sayHello(SocketChannel socketChannel) throws IOException {buf.clear();buf.put("hellp!\r\n".getBytes());buf.flip();System.out.println("will to send...");socketChannel.write(buf);System.out.println("achieve to send...");buf.clear();}private void registerChannel(Selector selector,SocketChannel socketChannel, int opRead) throws IOException {if (socketChannel == null) {return;}socketChannel.configureBlocking(false);socketChannel.register(selector, opRead);System.out.println("注册成功——读");}}




public class ClientSocketSelector {private static final int PORT = 1234;private static final String IP = "10.20.4.122";public static void main(String[] args) throws IOException {new ClientSocketSelector().init(args);}public void init(String...args) throws IOException{Selector selector = Selector.open();int port = PORT;String ip = IP;if(args.length != 0){ip = args[0];port = Integer.parseInt(args[1]);System.out.println(ip);System.out.println(port);}SocketChannel socketChannel = SocketChannel.open();socketChannel.configureBlocking(false);socketChannel.connect(new InetSocketAddress("localhost", port));//不能用socketChannel.socket().connect();亲身实践证明!用了就不能正常通信socketChannel.register(selector, SelectionKey.OP_CONNECT);while(true){int n = selector.select();if (n == 0) {continue;}Iterator it = selector.selectedKeys().iterator();while(it.hasNext()){SelectionKey key = (SelectionKey) it.next();it.remove();if (key.isConnectable()) {SocketChannel sc = (SocketChannel) key.channel();System.out.println("isConnectionPending:"+sc.isConnectionPending());if (sc.isConnectionPending()) sc.finishConnect();System.out.println("will to send...");sc.write(ByteBuffer.wrap("你好".getBytes()));System.out.println("achieve to send...");sc.register(selector, SelectionKey.OP_READ);}if (key.isReadable()) {readDataFromChannel(key);}}}}private ByteBuffer buf = ByteBuffer.allocate(1024);protected void readDataFromChannel(SelectionKey key) throws UnsupportedEncodingException, IOException {SocketChannel sc = (SocketChannel) key.channel();buf.clear();if (!sc.isConnected()) {return;}int count = 0;while((count = sc.read(buf)) > 0){System.out.println(buf.position());String str = new String(buf.array());System.out.println(str);}}}

原本以为只要一直让通道处于就绪状态就能不断的接收数据(IsReadable),测试后发现,一直处于被选择的键中,不能够接收到最新的数据。

只有将该键从已选择的键中取消,才能重新获得数据。

0 0
原创粉丝点击