zoukankan      html  css  js  c++  java
  • Java NIO网络编程demo

    使用Java NIO进行网络编程,看下服务端的例子

    import java.io.IOException;
    import java.net.InetAddress;
    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.Random;
    import java.util.Set;
    import java.util.concurrent.ConcurrentHashMap;
    
    public class Server {
        private static int PORT = 8000;
        private static final long PAUSE_BETWEEEN_MSGS = 10; // millisecs
        private static ByteBuffer echoBuffer = ByteBuffer.allocate(4);
        private static ByteBuffer sendBuffer = ByteBuffer.allocate(256);
        private static ConcurrentHashMap<Integer, SocketChannel> chm
                = new ConcurrentHashMap<Integer, SocketChannel>();
        private static int msg = 0;
    
    public static void main(String args[]) throws Exception {
            Selector selector = Selector.open();
            // Open a listener on each port, and register each one
            ServerSocketChannel ssc = ServerSocketChannel.open();
            ssc.configureBlocking(false);
            InetSocketAddress address = new InetSocketAddress("localhost",PORT);
            ssc.bind(address);
            ssc.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("Going to listen on " + PORT);
            while (true){
                selector.select();
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> it = selectedKeys.iterator();
    
                System.out.println(selectedKeys.size());
                while (it.hasNext()){
                    String msg = new String();
                    SelectionKey key = (SelectionKey) it.next();
                    if(key.isAcceptable()){
                        ServerSocketChannel sscNew = (ServerSocketChannel) key
                                .channel();
                        SocketChannel sc = sscNew.accept();
                        sc.configureBlocking(false);
                        // Add the new connection to the selector
                        sc.register(selector, SelectionKey.OP_READ);
                        // Add the socket channel to the list
                        chm.put(sc.hashCode(), sc);
                        it.remove();
                    }else if(key.isReadable()){
                        SocketChannel sc = (SocketChannel) key.channel();
                        int code = 0;
                        while ((code = sc.read(echoBuffer)) > 0) {
                            byte b[] = new byte[echoBuffer.position()];
                            echoBuffer.flip();
                            echoBuffer.get(b);
                            msg+=new String(b, "UTF-8");
                        }
    //                    if(msg.length()>1)
    //                        msg = msg.substring(0, msg.length()-2);
    
                        //client关闭时,收到可读事件,code = -1
                        if (code == -1 ||
                                msg.toUpperCase().indexOf("BYE")>-1){
                            chm.remove(sc.hashCode());
                            sc.close();
                        } else {
                            //code=0,消息读完或者echoBuffer空间不够时,部分消息内容下一次select后收到
                            echoBuffer.clear();
                        }
                        System.out.println("msg: " + msg  + " from: " + sc + "code:  " + code );
                        it.remove();
    
                        //注册可写通知
                        sc.register(selector,SelectionKey.OP_WRITE);
                    }else if(key.isWritable()){
                        SocketChannel client = (SocketChannel) key.channel();
                        String sendTxt = "Message from Server";
                        sendBuffer.put(sendTxt.getBytes());
                        sendBuffer.flip();
                        int code = 0;
    
                        //如果sendBuffer内容一次没有写完,会在下一次事件中处理吗?
                        while (client.write(sendBuffer) != 0){
                        }
                        if (code == -1 ){
                            chm.remove(client.hashCode());
                            client.close();
                        } else {
                            //code=0,消息写完
                            sendBuffer.clear();
                        }
                        it.remove();
                        System.out.println("Send message to client ");
    
                        //在读通知里面注册为写事件,所以这里还需要注册为读,否则不在接受客户端消息
                        client.register(selector,SelectionKey.OP_READ);
                    }
                }
                Thread.sleep(5000);
            }
        }
    }

    使用windows telnet与服务端交互,在windows telnet中,需要使用send命令来按行发送消息,如下所示

    一些说明:

    1.select操作为阻塞操作,直至至少一个事件发生

    2.server端只需注册accept事件

    3.read、write为非阻塞操作,需要在代码中判断返回结果

    4.read操作,如果接受的buffer大小不够,会在下一次select操作中接受

    5.write操作呢?如果消息没有发完,怎么处理,下面这种循环么?

    while (buffer.hasRemaining()){
                    socketChannel.write(buffer);
                }

    6.register会覆盖,所以在读写处理中交替注册

  • 相关阅读:
    word 改造成html表单
    ceshi
    easyUI 多功能datagrid 用户控件
    easyUI 多功能datagrid
    实现easyUI+.net 商品管理的用户控件
    通过sql 实现简单分页(not in)
    Jquery 插件开发
    Hello Swift
    关于const_cast转换
    undefined reference to '__android_log_print'.
  • 原文地址:https://www.cnblogs.com/darange/p/10954238.html
Copyright © 2011-2022 走看看