Giới thiệu
Bài viết này sẽ giúp bạn hiểu rõ về việc xây dựng một Blocking Server bằng Java Networking. Chúng ta sẽ tìm hiểu cách mà hai máy tính kết nối với nhau qua giao thức TCP thông qua Socket và ServerSocket, cũng như cách sử dụng Java IO để tương tác với dữ liệu thông qua các Socket.
Nội dung bài viết
Trước khi bắt đầu, bạn nên đọc những bài viết trước về Java Networking và Java IO để có nền tảng tốt nhất cho việc hiểu nội dung bài này. Việc bỏ qua có thể làm cho quá trình học trở nên khó khăn hơn.
Khái niệm về Socket
Trong Java Networking, mỗi Socket cung cấp cho bạn hai luồng: InputStream và OutputStream. Bằng cách này, bạn có thể đọc và ghi dữ liệu qua kết nối TCP.
Ví dụ mã nguồn cơ bản:
java
Socket socket;
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
PrintWriter writer = new PrintWriter(out);
writer.println("Hello");
writer.flush();
Ứng dụng Thực tế: Tính Bình Phương
Chúng ta sẽ xây dựng một chương trình Java đơn giản, nơi mà Client nhập một số và Server trả về bình phương của số đó. Dưới đây là mã nguồn cho Client và Server:
Mã nguồn Client:
java
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws IOException {
// Mở kết nối tới Server
Socket socket = new Socket("localhost", 8080);
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
PrintWriter writer = new PrintWriter(out);
BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
// Nhập số từ người dùng
System.out.print("Nhập một số (0 để thoát): ");
String userInput = consoleReader.readLine();
writer.println(userInput);
writer.flush();
// Nhận phản hồi từ Server
String response = reader.readLine();
System.out.println("Phản hồi từ Server: " + response);
// Đóng kết nối
socket.close();
}
}
Mã nguồn Server:
java
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("Server đang lắng nghe...\n");
while (true) {
Socket clientSocket = serverSocket.accept();
// Xử lý yêu cầu từ Client
new Thread(() -> {
handleClient(clientSocket);
}).start();
}
}
private static void handleClient(Socket clientSocket) {
try {
InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
PrintWriter writer = new PrintWriter(out);
String clientInput;
while ((clientInput = reader.readLine()) != null) {
int number = Integer.parseInt(clientInput);
if (number == 0) break;
int square = number * number;
writer.printf("%d bình phương là %d\n", number, square);
writer.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Cải tiến Server
Để cải thiện khả năng phục vụ, chúng ta sẽ:
- Tiếp tục lắng nghe kết nối từ nhiều Client.
- Cho phép Client gọi nhiều yêu cầu mà không bị ngắt kết nối.
Kết nối không bị ngắt
Sử dụng vòng lặp để cho phép Client có thể nhập nhiều số:
java
while (true) {
String userInputStr = consoleReader.readLine();
if (userInputStr.equals("0")) break;
writer.println(userInputStr);
}
Ưu và Nhược điểm của Blocking IO
Ưu điểm:
- Dễ dàng hiểu và triển khai.
- Cách tiếp cận đơn giản cho việc đọc và ghi dữ liệu.
Nhược điểm:
- Tốn tài nguyên, mỗi kết nối cần một thread mới.
- Khó mở rộng khi số lượng kết nối lớn.
Kết luận
Bài viết đã hướng dẫn bạn cách xây dựng một Blocking Server trong Java Networking. Hy vọng rằng thông qua bài viết này, bạn sẽ hiểu rõ hơn về cách hoạt động của giao tiếp giữa Client và Server, cũng như cách cải tiến mã nguồn để phục vụ nhiều người dùng cùng lúc.
Bạn nên thực hành bằng cách tự xây dựng Server và Client riêng của mình. Hãy thử thách và chinh phục các bài tập về nhà để hiểu sâu hơn nhé!
source: viblo