例子程序来自于
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
}
分享到:
相关推荐
### 基于Java NIO的非阻塞通信的研究与实现 #### 摘要 本文探讨了Java NIO(New I/O)框架中的非阻塞通信机制,并对其原理及应用进行了深入研究。NIO是一种现代I/O处理方法,通过引入缓冲区、通道和选择器等新概念...
NIO(New Input/Output)是Java平台中用于提高I/O性能的一种编程模型,与传统的BIO(Block I/O)模型相比,NIO提供了非阻塞的读写方式,能够...深入研究NIO的细节,有助于你在开发高效、高并发的服务时做出明智的选择。
Java NIO(非阻塞I/O)和AIO(异步I/O)是Java平台中用于提高I/O性能的重要技术。...通过研究这些代码和文档,开发者可以学习如何创建基于NIO和AIO的服务器,如何处理并发连接,以及如何优化性能。
与传统的-blocking I/O(阻塞I/O)相比,NIO的关键在于它允许程序在等待数据准备就绪时不必一直等待,而是可以继续处理其他任务,从而提高了程序的并发性能。 在Java NIO中,主要有以下核心概念: 1. **通道...
NIO(New IO)是Java平台中用于处理输入/输出操作的一种高级API,它在Java 1.4版本中引入,以替代传统的IO流模型。NIO提供了更高效、更灵活的数据传输方式...建议读者下载并仔细研究,以便更好地利用NIO提升程序性能。
同时,深入研究NIO和AIO的代码实现,了解它们如何通过通道、缓冲区和选择器来提高效率。通过对比分析,你将能够更好地理解各种I/O模型在不同场景下的优劣,以及如何根据需求选择合适的I/O模型。
这种方式使得主线程可以继续执行其他任务,提高程序的运行效率。 Future接口提供了如下方法: 1. **get()**:阻塞直到结果可用,然后返回结果。如果任务已经完成,此调用将立即返回;否则,它将等待任务完成。 2. *...
总之,Java非阻塞通信的研究涵盖了Java NIO和NIO.2的核心机制,以及如何在实际项目中应用这些技术来构建高并发、低延迟的系统。通过深入理解这些概念,开发者能够构建出更加高效、可扩展的Java应用程序。《Java非...
根据浦银国际研究报告,新能源汽车行业2023年展望非常乐观。报告指出,中国新能源汽车行业渗透率曲线继续加速上扬,预计2022年和2023年销量分别达到640万辆和802万辆,同比增长92%和25%,对应渗透率27.0%和36.9%。这...
未来的研究将继续探索新的催化剂组合和优化制备技术,以实现更加经济、高效且环境友好的燃料电池系统。这些进展对于推动燃料电池的商业化进程,以及在全球范围内实现可持续能源转型具有重大意义。
超级电容器的研究 超级电容器(Supercapacitors)是一种新型的储能装置,具有高能量密度的电化学电容器。它的结构主要由电极材料、电解质和隔膜组成。...但是,需要继续加强对其研究和发展,以提高其性能和降低成本。
同时,JAVA NIO(非阻塞I/O)库进一步提高了网络通信的效率,允许系统处理大量并发连接。 本课题的研究意义在于,随着互联网的普及,网络通信已经成为日常生活中不可或缺的一部分。无论是个人社交、商业交流还是...
在Java中,可以查看NIO相关的类,如java.nio.channels.Selector、java.nio.channels.SocketChannel等,研究它们如何实现非阻塞IO。在Node.js中,可以研究libuv库,它是Node.js实现异步IO的基石,提供了对多种平台的...
在客户端 NioSocketChannel 向 Sub Reactor 注册的过程中,主 Reactor 会将新连接的 Channel 和相关的 ChannelPipeline 转交给一个从 Reactor 线程,这个线程会继续处理连接的读写事件。Sub Reactor 线程组通常配置...
NIO 支持非阻塞 I/O 操作,即在发起读写请求后,不会等待 I/O 操作完成,而是继续执行后续任务,这样可以有效利用 CPU 资源。 - **阻塞 IO 与非阻塞 IO 对比**:阻塞 IO 在发起读写操作时会阻塞当前线程直到操作完成...
通过研究这个"基于Java的实例源码-异步IO框架 Cindy.zip",开发者不仅可以掌握Java NIO的基本概念,还能深入了解异步编程和事件驱动模型,为构建高效、可扩展的Java应用程序打下坚实基础。同时,通过对比不同异步...