zoukankan      html  css  js  c++  java
  • NIO Channel Socket套接字相关Channel

    阻塞非阻塞:

    NIO中的Channel主要分为两大类:一类是FileChannel,另一类是SocketChannel。NIO提供的核心非阻塞特性主要针对SocketChannel类,全部socket通道类(DatagramChannel、SocketChannel和ServerSocketChannel)都是由位于java.nio.channels.spi包中的AbstractSelectableChannel引申而来。这意味着我们可以用一个Selector对象来执行socket通道的有条件的选择(readiness selection)。

    SelectableChannel抽象类提供的方法:

      请注意DatagramChannel和SocketChannel实现定义读和写功能的接口而ServerSocketChannel不实现。ServerSocketChannel负责监听传入的连接和创建新的SocketChannel对象,它本身从不传输数据。全部socket通道类(DatagramChannel、SocketChannel和ServerSocketChannel)在被实例化时都会创建一个对等socket对象。这些是我们所熟悉的来自java.net的类(Socket、ServerSocket和DatagramSocket),它们已经被更新以识别通道。对等socket可以通过调用socket( )方法从一个通道上获取。此外,这三个java.net类现在都有getChannel( )方法。

      虽然每个socketChannnel(在java.nio.channels包中)都有一个关联的java.net socket对象,却并非所有的socket都有一个关联的通道。如果您用传统方式(直接实例化)创建了一个Socket对象,它就不会有关联的SocketChannel并且它的getChannel( )方法将总是返回null。

    示例代码:

        @Test
        public void socketTest() {
            ServerSocket serverSocket = null;
            try {
                serverSocket = new ServerSocket(8080);
            } catch (IOException e) {
                e.printStackTrace();
            }
            ServerSocketChannel channel = serverSocket.getChannel();
            assert (channel == null);
        }
    

      SocketChannel委派协议操作给对等socket对象。如果在通道类中存在似乎重复的socket方法,那么将有某个新的或者不同的行为同通道类上的这个方法相关联。

    非阻塞模式:

      默认为阻塞模式,示例如下:

        @Test
        public void socketChannelTest() throws Exception {
            ServerSocketChannel ssc = ServerSocketChannel.open();
            ssc.socket().bind(new InetSocketAddress(8080));
            assert (ssc.isBlocking());
            ssc.configureBlocking(false);
            assert (!ssc.isBlocking());
    
            SocketChannel sc = SocketChannel.open();
            sc.connect(new InetSocketAddress("localhost", 8080));
            
        }
    configureBlocking()是阻塞操作

    阻塞非阻塞开关锁:

      我们也会需要防止socket通道的阻塞模式被更改。API中有一个blockingLock( )方法,该方法会返回一个非透明的对象引用。返回的对象是通道实现修改阻塞模式时内部使用的。只有拥有此对象的锁的线程才能更改通道的阻塞模式(对象的锁是用同步的Java密码获取的)。对于确保在执行代码的关键部分时socket通道的阻塞模式不会改变以及在不影响其他线程的前提下暂时改变阻塞模式来说,这个方法都是非常方便的。

    代码示例:

        /**
         * configureBlocking Test
         * @throws Exception
         */
        @Test
        public void socketChannelConfigureBlockingTest() throws Exception {
            ServerSocketChannel ssc = ServerSocketChannel.open();
            ssc.socket().bind(new InetSocketAddress(8080));
            assert (ssc.isBlocking());
            ssc.configureBlocking(false);
            assert (!ssc.isBlocking());
            Object lock = ssc.blockingLock();
            Thread thread = new Thread(()->{
                Date date = new Date();
                try {
                    TimeUnit.SECONDS.sleep(3);
                    date = new Date();
                    //阻塞操作
                    ssc.configureBlocking(true);
                } catch (Exception e) {
                    e.printStackTrace();
                    assert (false);
                }
                assert (ssc.isBlocking());
                assert (new Date().getTime()-date.getTime()>=6000);
            });
            thread.start();
            synchronized (lock){
                TimeUnit.SECONDS.sleep(10);
            }
            thread.join();
        }
  • 相关阅读:
    SVN与TortoiseSVN实战:标签与分支
    IOS性能调优系列:使用Zombies动态分析内存中的僵尸对象
    IOS性能调优系列:使用Allocation动态分析内存使用情况
    IOS性能调优系列:使用Instruments动态分析内存泄漏
    IOS性能调优系列:Analyze静态分析
    2014年个人知乎收藏夹整理
    IOS开发环境更换后重新制作Provisioning Profile证书详解
    使用VS2010编译MongoDB C++驱动详解
    ACE服务端编程1:使用VS2010编译ACE6.0及从ACE5.6升级的注意事项
    std::string在多字节字符集环境下substr的实现方法
  • 原文地址:https://www.cnblogs.com/heapStark/p/8176461.html
Copyright © 2011-2022 走看看