introduction
In computer networks, multiplexing refers to the merging of multiple I/O operations into the same thread or process through a mechanism to improve the efficiency of the system. In Java, the Selector class can be used to implement I/O multiplexing-based mode, commonly known as the Select model, which enables a single thread to handle I/O operations on multiple network connections.
Java packages provide Selector-based I/O operations, allowing you to listen to multiple channels (channels) simultaneously in a single thread. This is very useful for high concurrency network applications, and can avoid creating independent threads for each connection, thereby reducing thread overhead.
1. Select model overview
The Select model allows a thread to listen to multiple I/O events at the same time (such as read, write, connect, etc.) and the thread processes the event when a channel is ready for an operation. In Java,Selector
Provides such a mechanism that is used in conjunction with multiple channels.
2. Main categories
- Selector: Selector, used to monitor I/O events on multiple channels.
-
SelectableChannel: The optional channel, usually
SocketChannel
orServerSocketChannel
。 - SelectionKey: Select key, indicating the relationship between a channel and a selector.
Ideas for project implementation
-
Create Selector: Create one first
Selector
, it is used to manage multiple channels. -
Open the channel: Create and open
ServerSocketChannel
(used to listen to client connections) andSocketChannel
(Used to communicate with clients). -
Register channel: Register these channels to
Selector
On, specify the I/O operations they are interested in (such as connection, read, write). -
Listen to events: Call
()
Method Wait for the channel to be ready for I/O operation. -
Handle events: When a channel is ready for I/O operation, obtain the channel's
SelectionKey
and process corresponding operations (such as reading data or sending responses).
IV. Implement code
Here is a simple Java example showing how to use itSelector
Implement a multiplexed server.
import .*; import .*; import .*; import .*; import .*; public class MultiplexingServer { public static void main(String[] args) throws IOException { // Create a Selector to listen to multiple channels Selector selector = (); // Open ServerSocketChannel to listen to client connection requests ServerSocketChannel serverSocketChannel = (); (false); // Set to non-blocking mode ().bind(new InetSocketAddress(8080)); // Register ServerSocketChannel to Selector and listen for ACCEPT events (selector, SelectionKey.OP_ACCEPT); ("Server started on port 8080..."); while (true) { // Wait for the ready event (); // Get the ready SelectionKey collection Set<SelectionKey> readyKeys = (); Iterator<SelectionKey> iterator = (); while (()) { SelectionKey key = (); (); // Remove the currently processed key try { if (()) { // There is a new client connection handleAccept(serverSocketChannel, selector); } else if (()) { // A client sent data handleRead(key); } else if (()) { // Need to write data to the client handleWrite(key); } } catch (IOException e) { (); try { ().close(); } catch (IOException ex) { (); } } } } } // Handle access client connection private static void handleAccept(ServerSocketChannel serverSocketChannel, Selector selector) throws IOException { SocketChannel clientChannel = (); (false); // Register the client channel to the selector to listen to the read event (selector, SelectionKey.OP_READ); ("Client connected: " + ()); } // Process data sent by the client private static void handleRead(SelectionKey key) throws IOException { SocketChannel clientChannel = (SocketChannel) (); ByteBuffer buffer = (1024); int bytesRead = (buffer); if (bytesRead == -1) { // The client closes the connection ("Client disconnected: " + ()); (); (); return; } (); // Ready to read data ("Received data: " + new String((), 0, bytesRead)); // Change the channel to a writable state and prepare to send data (SelectionKey.OP_WRITE); } // Process writing data to the client private static void handleWrite(SelectionKey key) throws IOException { SocketChannel clientChannel = (SocketChannel) (); String response = "Hello from server!"; ByteBuffer buffer = (()); (buffer); // Send data ("Sent data to client: " + response); // After sending, re-register as a readable event (SelectionKey.OP_READ); } }
5. Code interpretation
Selector Initialization:
Selector selector = ();
Here we created aSelector
Object, used to manage I/O events on all channels.
ServerSocketChannel Settings:
ServerSocketChannel serverSocketChannel = (); (false); ().bind(new InetSocketAddress(8080));
ServerSocketChannel is used to listen for client connection requests and is set to non-blocking mode.
Channel registration:
(selector, SelectionKey.OP_ACCEPT);
Register ServerSocketChannel to the Selector, specifying that the event we are interested in is Accept Connection (SelectionKey.OP_ACCEPT).
Event Polling:
(); Set<SelectionKey> readyKeys = ();
The select() method blocks until at least one channel is ready for I/O operation. Then use selectedKeys() to get the prepared SelectionKey collection.
Handle different events:
Accept connection:
if (()) { handleAccept(serverSocketChannel, selector); }
If it is accepting a connection event, we callhandleAccept
To access the client connection and register it toSelector
The above is to listen to the reading event.
Read data:
if (()) { handleWrite(key); }
If it is writing data events, we callhandleWrite
To respond to client data.
-
Client processing:
- exist
handleRead
In , we read the data sent by the client and transfer the channel tointerestOps
Change toOP_WRITE
, means that the next step is to send data. - exist
handleWrite
In , we send response data to the client and after the sending is completed, the channel’sinterestOps
Change backOP_READ
, waiting for the next data read.
- exist
6. Summary
This article implements a simple multiplexed Select model server. Provided through Java NIOSelector
andChannel
,We are able to handle connections and data read and write operations of multiple clients simultaneously in one thread. Compared with the traditional multithreading model, NIO multiplexing can significantly improve server performance, especially in high concurrency network applications.
The above is the detailed explanation of the Java multiplexing select model example. For more information about Java multiplexing select model, please pay attention to my other related articles!