zoukankan      html  css  js  c++  java
  • Java Socket NIO入门

    Java Socket、SocketServer的读写、连接事件监听,都是阻塞式的。Java提供了另外一种非阻塞式读写、连接事件监听方式——NIO。本文简单的介绍一个NIO Socket入门例子,原理以及详细用法,参考后续文章

    服务端代码

    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.Iterator;
    
    /**
     * 
     * NIO Socket Server
     * @author coshaho
     */
    public class NIOServer
    {
        public static void main(String[] args) throws IOException
        {
            // 启动Socket Server Channel
            ServerSocketChannel server = ServerSocketChannel.open();
            server.bind(new InetSocketAddress(8001));
            server.configureBlocking(false);
            
            // 绑定选择器,注册连接监听事件
            Selector selector = Selector.open();
            server.register(selector, SelectionKey.OP_ACCEPT);
            
            SelectorHandler handler = new SelectorHandler();
            while(true)
            {
                // 非阻塞监听注册事件
                if(selector.select(2000) == 0)
                {
                    System.out.println("No selection");
                    continue;
                }
                
                // 发现注册事件,依次处理
                Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator();
                while(keyIter.hasNext())
                {
                    SelectionKey key = keyIter.next();
                    if(key.isAcceptable())
                    {
                        handler.doAccept(key);
                    }
                    
                    if(key.isReadable())
                    {
                        handler.doRead(key);
                    }
                    
                    if(key.isValid() && key.isWritable())
                    {
                        handler.doWrite(key);
                    }
                    
                    keyIter.remove();
                }
            }
        }
        
        /**
         * 事件处理器
         * @author h00219638
         */
        public static class SelectorHandler
        {
            // 连接请求处理
            public void doAccept(SelectionKey key) throws IOException
            {
                SocketChannel socket = ((ServerSocketChannel)key.channel()).accept();
                socket.configureBlocking(false);
                // 注册数据读取事件
                socket.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocate(1024));
            }
            
            public void doRead(SelectionKey key) throws IOException
            {
                SocketChannel socket = (SocketChannel)key.channel();
                
                // 也可以临时分配ByteBuffer
                ByteBuffer buf = (ByteBuffer) key.attachment();
                buf.clear();
                
                if(-1 == socket.read(buf))
                {
                    socket.close();
                }
                else
                {
                    System.out.println("Server received: " + new String(buf.array(), 0, buf.limit()));
    
                    /**
                     * public static final int OP_READ = 1 << 0; 
                       public static final int OP_WRITE = 1 << 2; 
                       public static final int OP_CONNECT = 1 << 3; 
                       public static final int OP_ACCEPT = 1 << 4; 
                     */
                    // 增加写事件,写事件会不断被触发,数据写完后必须取消写事件监听
                    key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
                }
            }
            
            public void doWrite(SelectionKey key) throws IOException
            {
                SocketChannel socket = (SocketChannel)key.channel();
                ByteBuffer buf = (ByteBuffer) key.attachment();
                
                // 写数据之前注意调用flip方法,重置指针
                buf.flip();
                System.out.println("Write: " + new String(buf.array(), 0, buf.limit()));
                socket.write(buf);
                if(!buf.hasRemaining())
                {
                    // 取消写事件监听
                    key.interestOps(key.interestOps() &~  SelectionKey.OP_WRITE);
                }
                buf.compact();
            }
        }
        
    }

     客户端代码

    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.SocketChannel;
    
    import org.drools.core.util.StringUtils;
    
    /**
     * 
     * NIO Socket Client
     * @author coshaho
     */
    public class NIOClient
    {
        public static void main(String[] args) throws IOException
        {
            SocketChannel socket = SocketChannel.open();
            socket.configureBlocking(false);
            
            if(!socket.connect(new InetSocketAddress("localhost", 8001)))
            {
                System.out.println("Not connect");  
                // 正真的连接
                while(!socket.finishConnect())
                {
                    System.out.println("Not finishConnect");  
                }
            }
            
            ByteBuffer wBuf = ByteBuffer.wrap("Hello, server".getBytes());
            while(wBuf.hasRemaining())
            {
                socket.write(wBuf);
            }
            
            ByteBuffer rBuf = ByteBuffer.allocate(8);
            StringBuffer sBuf = new StringBuffer();
            while(-1 != (socket.read(rBuf)))
            {
                rBuf.flip();
                String s = new String(rBuf.array(), 0, rBuf.limit());
                sBuf.append(s);
                rBuf.clear();
                if(StringUtils.isEmpty(s))
                {
                    break;
                }
                
            }
            
            System.out.println("Client received: " + sBuf.toString());
            socket.close();
        }
    }
  • 相关阅读:
    [C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例
    玩转Asp.net MVC 的八个扩展点
    float实例讲解
    C#高性能TCP服务的多种实现方式
    如何把SQLServer数据库从高版本降级到低版本?
    ASP.NET MVC Area使用-将Area设置成独立项目
    如何使用ping和tracert命令测试网站访问速度
    ASP.NET MVC 入门10、Action Filter 与 内置的Filter实现(实例-防盗链)
    MVC Action Filter
    c#中单元测试
  • 原文地址:https://www.cnblogs.com/coshaho/p/8082359.html
Copyright © 2011-2022 走看看