`
dodoflying
  • 浏览: 176467 次
社区版块
存档分类
最新评论

NIO继续研究

阅读更多
例子程序来自于The Java Developers Almanac 1.4
http://javaalmanac.com/?l=ex

Creating a Non-Blocking Socket
 // Creates a non-blocking socket channel for the specified host name and port.
    // connect(); is called on the new channel before it is returned.
    public static SocketChannel createSocketChannel(String hostName, int port); throws IOException {
        // Create a non-blocking socket channel
        SocketChannel sChannel = SocketChannel.open();;
        sChannel.configureBlocking(false);;
    
        // Send a connection request to the server; this method is non-blocking
        sChannel.connect(new InetSocketAddress(hostName, port););;
        return sChannel;
    }

    // Create a non-blocking socket and check for connections
    try {
        // Create a non-blocking socket channel on port 80
        SocketChannel sChannel = createSocketChannel("hostname.com", 80);;
    
        // Before the socket is usable, the connection must be completed
        // by calling finishConnect();, which is non-blocking
        while (!sChannel.finishConnect();); {
            // Do something else
        }
        // Socket channel is now ready to use
    } catch (IOException e); {
    }




Reading from a SocketChannel
// Create a direct buffer to get bytes from socket.
    // Direct buffers should be long-lived and be reused as much as possible.
    ByteBuffer buf = ByteBuffer.allocateDirect(1024);;
    
    try {
        // Clear the buffer and read bytes from socket
        buf.clear();;
        int numBytesRead = socketChannel.read(buf);;
    
        if (numBytesRead == -1); {
            // No more bytes can be read from the channel
            socketChannel.close();;
        } else {
            // To read the bytes, flip the buffer
            buf.flip();;
    
            // Read the bytes from the buffer ...;
            // see e159 Getting Bytes from a ByteBuffer
        }
    } catch (IOException e); {
        // Connection may have been closed
    }


Getting Bytes from a ByteBuffer
A ByteBuffer has a capacity that determines how many bytes it contains. This capacity can never change. Any byte in the buffer can be retrieved using the absolute version of get(), which takes an index in the range [0..capacity-1].
The bytes in a ByteBuffer can also be retrieved using the relative version of get(), which uses the position and limit properties of the buffer. In particular, this version of get() retrieves the byte at the position and advances the position by one. get() cannot retrieve bytes past the limit (even though the limit might be less than the capacity). The position is always <= limit and limit is always <= capacity.

 // Create an empty ByteBuffer with a 10 byte capacity
    ByteBuffer bbuf = ByteBuffer.allocate(10);;
    
    // Get the ByteBuffer's capacity
    int capacity = bbuf.capacity();; // 10
    
    // Use the absolute get();.
    // This method does not affect the position.
    byte b = bbuf.get(5);; // position=0
    
    // Set the position
    bbuf.position(5);;
    
    // Use the relative get();
    b = bbuf.get();;
    
    // Get the new position
    int pos = bbuf.position();; // 6
    
    // Get remaining byte count
    int rem = bbuf.remaining();; // 4
    
    // Set the limit
    bbuf.limit(7);; // remaining=1
    
    // This convenience method sets the position to 0
    bbuf.rewind();; // remaining=7


Writing to a SocketChannel
 // Create a direct buffer to get bytes from socket.
    // Direct buffers should be long-lived and be reused as much as possible.
    ByteBuffer buf = ByteBuffer.allocateDirect(1024);;
    
    try {
        // Fill the buffer with the bytes to write;
        // see e160 Putting Bytes into a ByteBuffer
        buf.put((byte);0xFF);;
    
        // Prepare the buffer for reading by the socket
        buf.flip();;
    
        // Write bytes
        int numBytesWritten = socketChannel.write(buf);;
    } catch (IOException e); {
        // Connection may have been closed
    }


Using a Selector to Manage Non-Blocking Socket
Although you could poll each non-blocking socket for events, a more convenient and efficient method is to use a selector to manage the channels. The selector efficiently monitors the channels for changes and reports the events through a single method call.
The first step is to register a channel with a selector. The registration process yields an object called a selection key which identifies the selector/socket channel pair (a channel could be registered with another selector for different events). When an event occurs on a channel, the selector returns the selection key for that channel. The selection key also contains the type of event that occurred.

This example creates two sockets and registers them with a selector. The example then uses the selector to listen for events.

See also e179 Using a Selector to Manage Non-Blocking Server Sockets.


 // Create a selector and register two socket channels
    Selector selector = null;
    try {
        // Create the selector
        selector = Selector.open();;
    
        // Create two non-blocking sockets. This method is implemented in
        // e173 Creating a Non-Blocking Socket.
        SocketChannel sChannel1 = createSocketChannel("hostname.com", 80);;
        SocketChannel sChannel2 = createSocketChannel("hostname.com", 80);;
    
        // Register the channel with selector, listening for all events
        sChannel1.register(selector, sChannel1.validOps(););;
        sChannel2.register(selector, sChannel1.validOps(););;
    } catch (IOException e); {
    }
    
    // Wait for events
    while (true); {
        try {
            // Wait for an event
            selector.select();;
        } catch (IOException e); {
            // Handle error with selector
            break;
        }
    
        // Get list of selection keys with pending events
        Iterator it = selector.selectedKeys();.iterator();;
    
        // Process each key at a time
        while (it.hasNext();); {
            // Get the selection key
            SelectionKey selKey = (SelectionKey);it.next();;
    
            // Remove it from the list to indicate that it is being processed
            it.remove();;
    
            try {
                processSelectionKey(selKey);;
            } catch (IOException e); {
                // Handle error with channel and unregister
                selKey.cancel();;
            }
        }
    }
    
    public void processSelectionKey(SelectionKey selKey); throws IOException {
        // Since the ready operations are cumulative,
        // need to check readiness for each operation
        if (selKey.isValid(); && selKey.isConnectable();); {
            // Get channel with connection request
            SocketChannel sChannel = (SocketChannel);selKey.channel();;
    
            boolean success = sChannel.finishConnect();;
            if (!success); {
                // An error occurred; handle it
    
                // Unregister the channel with this selector
                selKey.cancel();;
            }
        }
        if (selKey.isValid(); && selKey.isReadable();); {
            // Get channel with bytes to read
            SocketChannel sChannel = (SocketChannel);selKey.channel();;
    
            // See e174 Reading from a SocketChannel
        }
        if (selKey.isValid(); && selKey.isWritable();); {
            // Get channel that's ready for more bytes
            SocketChannel sChannel = (SocketChannel);selKey.channel();;
    
            // See e175 Writing to a SocketChannel
        }
    }


Creating a Non-Blocking Server Socket
This example shows how to create a non-blocking server socket. A non-blocking server socket requires a server socket channel.
 // Create a non-blocking server socket and check for connections
    try {
        // Create a non-blocking server socket channel on port 80
        ServerSocketChannel ssChannel = ServerSocketChannel.open();;
        ssChannel.configureBlocking(false);;
        int port = 80;
        ssChannel.socket();.bind(new InetSocketAddress(port););;
    
        // See e178 Accepting a Connection on a ServerSocketChannel
        // for an example of accepting a connection request
    } catch (IOException e); {
    }


e178. Accepting a Connection on a ServerSocketChannel
// Get port that received the connection request; this information
    // might be useful in determining how to handle the connection
    int localPort = serverSocketChannel.socket();.getLocalPort();;
    
    try {
        // Accept the connection request.
        // If serverSocketChannel is blocking, this method blocks.
        // The returned channel is in blocking mode.
        SocketChannel sChannel = serverSocketChannel.accept();;
    
        // If serverSocketChannel is non-blocking, sChannel may be null
        if (sChannel == null); {
            // There were no pending connection requests; try again later.
            // To be notified of connection requests,
            // see e179 Using a Selector to Manage Non-Blocking Server Sockets.
        } else {
            // Use the socket channel to communicate with the client
            // See e176 Using a Selector to Manage Non-Blocking Sockets.
        }
    } catch (IOException e); {
    }


e179. Using a Selector to Manage Non-Blocking Server Sockets
For more information about selectors, see e176 Using a Selector to Manage Non-Blocking Sockets.
This example creates two server sockets and registers them with a selector. The example then uses the selector to listen for events.

try {
        // Create the selector
        Selector selector = Selector.open();;
    
        // Create two non-blocking server sockets on 80 and 81
        ServerSocketChannel ssChannel1 = ServerSocketChannel.open();;
        ssChannel1.configureBlocking(false);;
        ssChannel1.socket();.bind(new InetSocketAddress(80););;
    
        ServerSocketChannel ssChannel2 = ServerSocketChannel.open();;
        ssChannel2.configureBlocking(false);;
        ssChannel2.socket();.bind(new InetSocketAddress(81););;
    
        // Register both channels with selector
        ssChannel1.register(selector, SelectionKey.OP_ACCEPT);;
        ssChannel2.register(selector, SelectionKey.OP_ACCEPT);;
    
        while (true); {
            // Wait for an event
            selector.select();;
    
            // Get list of selection keys with pending events
            Iterator it = selector.selectedKeys();.iterator();;
    
            // Process each key
            while (it.hasNext();); {
                // Get the selection key
                SelectionKey selKey = (SelectionKey);it.next();;
    
                // Remove it from the list to indicate that it is being processed
                it.remove();;
    
                // Check if it's a connection request
                if (selKey.isAcceptable();); {
                    // Get channel with connection request
                    ServerSocketChannel ssChannel = (ServerSocketChannel);selKey.channel();;
    
                    // See e178 Accepting a Connection on a ServerSocketChannel
                    // for an example of accepting a connection request
                }
            }
        }
    } catch (IOException e); {
    }


e180. Detecting When a Non-Blocking Socket Is Closed by the Remote Host
The only way to detect that the remote host has closed the connection is to attempt to read or write from the connection. If the remote host properly closed the connection, read() will return -1. If the connection was not terminated normally, read() and write() will throw an exception.
When using a selector to process events from a non-blocking socket, the selector will try to return an OP_READ or OP_WRITE event if the remote host has closed the socket.

try {
        // Read from socket
        int numBytesRead = socketChannel.read(buf);;
    
        if (numBytesRead == -1); {
            // No more bytes can be read from the channel
            socketChannel.close();;
        } else {
            // Read the bytes from the buffer
        }
    } catch (IOException e); {
        // Connection may have been closed
    }
    
    try {
        // Write to socket
        int numBytesWritten = socketChannel.write(buf);;
    } catch (IOException e); {
        // Connection may have been closed
    }
分享到:
评论

相关推荐

    JavaNIO chm帮助文档

    Java NIO系列教程(一) Java NIO 概述 Java NIO系列教程(二) Channel Java NIO系列教程(三) Buffer Java NIO系列教程(四) Scatter/Gather Java NIO系列教程(五) 通道之间的数据传输 Java NIO系列教程(六)...

    NIO 入门.chm,NIO 入门.chm

    NIO入门.chm NIO入门.chm NIO入门.chm

    java NIO 视频教程

    当数据被写入到缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。 Java NIO: Selectors(选择器) Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的...

    java nio 实现socket

    java nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socket

    java NIO和java并发编程的书籍

    java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java...

    基于JavaNIO的非阻塞通信的研究与实现

    基于JavaNIO的非阻塞通信的研究与实现

    Java NIO 中文 Java NIO 中文 Java NIO 中文文档

    Java NIO 深入探讨了 1.4 版的 I/O 新特性,并告诉您如何使用这些特性来极大地提升您所写的 Java 代码的执行效率。这本小册子就程序员所面临的有代表性的 I/O 问题作了详尽阐述,并讲解了 如何才能充分利用新的 I/O ...

    java NIO.zip

    java NIO.zip

    Java NIO系列教程(一) Java NIO 概述

    Java NIO系列教程(一) Java NIO 概述

    Java NIO英文高清原版

    Java NIO英文高清原版

    java nio 包读取超大数据文件

    Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据...

    Java IO NIO and NIO 2 无水印pdf

    Java IO NIO and NIO 2 英文无水印pdf pdf所有页面使用FoxitReader和PDF-XChangeViewer测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn...

    NIO和AIO介绍

    NIO和AIO介绍NIO和AIO介绍NIO和AIO介绍NIO和AIO介绍NIO和AIO介绍NIO和AIO介绍NIO和AIO介绍NIO和AIO介绍NIO和AIO介绍NIO和AIO介绍NIO和AIO介绍NIO和AIO介绍NIO和AIO介绍NIO和AIO介绍NIO和AIO介绍

    尚硅谷Java视频_NIO 视频教程

    尚硅谷_NIO_NIO 与 IO 区别 ·02. 尚硅谷_NIO_缓冲区(Buffer)的数据存取 ·03. 尚硅谷_NIO_直接缓冲区与非直接缓冲区 ·04. 尚硅谷_NIO_通道(Channel)的原理与获取 ·05. 尚硅谷_NIO_通道的数据传输与内存映射文件 ...

    java socket nio 研究

    NULL 博文链接:https://zfms.iteye.com/blog/1535594

    nio的excel导出

    nio的excel导出

    Java IO NIO and NIO 2 epub

    Java IO NIO and NIO 2 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除

    java NIO 中文版

    讲解了 JavaIO 与 JAVA NIO区别,JAVA NIO设计理念,以及JDK中java NIO中语法的使用

    java基于NIO实现Reactor模型源码.zip

    java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现...

    JAVA NIO 按行读取大文件,支持 GB级别

    本类,是专门为了处理大文件... 如果 到达 fbb的结尾 还没有结束,就再通过nio读取一段字节,继续处理。 由于对于本程序 116个字节以上的行才有意义,所以 在next实现方法中,有对 116 长度的判断,否则返回 null

Global site tag (gtag.js) - Google Analytics