Giới Thiệu
Bài viết này sẽ giúp bạn hiểu về Java Networking và Java IO để tạo một máy chủ, đồng thời giải quyết vấn đề trong cơ chế blocking của Java IO thông qua công nghệ Java NIO (Java New Input/Output).
Java NIO (Java New Input/Output)
Java NIO không phải là Java Non-blocking IO mà là một thay thế cho Java IO và Java Networking. Nó giới thiệu những khái niệm mới như Channel, Buffer, và Selector. Chúng ta sẽ cùng tìm hiểu từng khái niệm này và cách mà chúng khác biệt so với Java IO.
Channel và Buffer
Trong Java IO, chúng ta sử dụng Streams để xử lý dữ liệu. Ngược lại, Java NIO bắt đầu từ Channel và kết thúc cũng tại Channel. Để tưởng tượng dễ hơn, hãy xem Channel giống như một kênh dẫn nước từ nguồn vào máy móc. Mỗi Channel có thể không chỉ là một file mà còn có thể là các Socket.
Buffer trong Java NIO giống như một dụng cụ vận chuyển, chứa dữ liệu lấy từ Channel. Nó giúp cho việc ghi và đọc dữ liệu trở nên dễ dàng hơn. Buffer có các chỉ số quan trọng như position, limit, và capacity mà bạn cần nắm rõ.
Ví dụ mã nguồn:
java
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class CopyBytes {
public static void main(String[] args) throws IOException {
Path source1 = Paths.get("source1.txt");
Path source2 = Paths.get("source2.txt");
FileChannel channel1 = null;
FileChannel channel2 = null;
try {
channel1 = FileChannel.open(source1, StandardOpenOption.READ);
channel2 = FileChannel.open(source2, StandardOpenOption.WRITE);
ByteBuffer buffer = ByteBuffer.allocate(3);
while (channel1.read(buffer) > 0) {
buffer.flip();
channel2.write(buffer);
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (channel1 != null) channel1.close();
if (channel2 != null) channel2.close();
}
}
}
Tìm Hiểu Về Buffer
Buffer trong Java NIO là một mảng byte, với các thông số chính là capacity, limit, và position. Bạn có thể thực hiện nhiều thao tác với Buffer như flip(), clear(), compact(), và mark()/reset() để quản lý dữ liệu hiệu quả hơn.
Xây Dựng Máy Chủ Non-Blocking với Java NIO
Tiếp theo, chúng ta sẽ xây dựng một máy chủ sử dụng Java NIO. Máy chủ này có khả năng xử lý nhiều kết nối đồng thời mà không bị blocking. Đầu tiên, hãy xem đoạn mã cho phần Client.
java
import java.io.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
public class Client {
public static void main(String[] args) throws IOException {
SocketChannel socketChannel = SocketChannel.open();
InetAddress localhost = InetAddress.getByName("localhost");
InetSocketAddress inetSocketAddress = new InetSocketAddress(localhost, 8080);
socketChannel.connect(inetSocketAddress);
// ---- CODE CONTINUES ----
}
}
Tiếp theo, hãy xem đoạn mã cho phần Server:
java
import java.io.*;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
public class Server {
public static void main(String[] args) throws IOException {
System.out.println("Server đang chạy trên cổng 8080");
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// ---- CODE CONTINUES ----
}
}
Tối Ưu Hóa Máy Chủ
Một trong những lợi ích tích cực nhất của việc sử dụng Non-blocking IO là tiết kiệm tài nguyên hệ thống. Với Java NIO, chỉ cần 1 Thread sẽ giúp chúng ta xử lý nhiều kết nối cùng lúc mà không cần phải tạo nhiều Threads.
Lợi Điểm và Nhược Điểm của Non-blocking Server
Lợi Điểm:
- Tiết kiệm tài nguyên hệ thống.
- Khả năng mở rộng tốt hơn khi nhiều khách hàng cùng yêu cầu phục vụ.
Nhược Điểm:
- Khó triển khai hơn do cần quản lý nhiều tác vụ trong một Thread.
Kết Luận
Bài viết này đã trang bị cho bạn kiến thức cơ bản về Java NIO và việc xây dựng một máy chủ Non-blocking. Hy vọng với kiến thức này, bạn sẽ có thể áp dụng để phát triển các ứng dụng mạng hiệu quả hơn.
Link đến bài viết gốc
source: viblo