Bài viết này sẽ hướng dẫn cách tạo một ứng dụng mô phỏng việc tải lên tệp tin từ máy khách đến máy chủ sử dụng các lớp Socket và ServerSocket kết hợp với kỹ thuật đa luồng.
Máy khách Client
Để tạo demo này, bạn không cần thêm bất kỳ thư viện phụ thuộc nào, chỉ cần khởi tạo một dự án mới với tênClient.
Sử dụng lớp Socket để tạo máy khách:
import java.io.*;
import java.net.*;
public class FileUploader {
public static void main(String[] args) throws IOException {
// Tạo một đối tượng Socket kết nối đến máy chủ tại địa chỉ IP và cổng đã định
Socket clientSocket = new Socket("127.0.0.1", 8083);
// Khởi tạo đối tượng File đại diện cho tệp tin cần tải lên
File sourceFile = new File("E:" + File.separator + "1.jpg");
// Tạo một luồng đọc từ tệp tin
FileInputStream fileReader = new FileInputStream(sourceFile);
// Lấy luồng ghi dữ liệu từ đối tượng Socket
OutputStream dataSender = clientSocket.getOutputStream();
// Đọc dữ liệu từ tệp tin và gửi đi qua luồng
byte[] buffer = new byte[(int) sourceFile.length()];
int bytesRead;
while ((bytesRead = fileReader.read(buffer)) != -1) {
dataSender.write(buffer, 0, bytesRead);
}
// Đóng luồng ghi dữ liệu
clientSocket.shutdownOutput();
// Nhận phản hồi từ máy chủ
InputStream responseReceiver = clientSocket.getInputStream();
while ((bytesRead = responseReceiver.read(buffer)) != -1) {
// In ra thông báo từ máy chủ
System.out.println(new String(buffer, 0, bytesRead));
}
// Đóng các luồng đã mở
fileReader.close();
clientSocket.close();
}
}
Máy chủ Server
Tương tự như trên, tạo một dự án mới và sử dụng lớpServerSocket để thiết lập máy chủ:
import java.io.*;
import java.net.*;
import java.util.concurrent.*;
public class FileReceiver {
public static void main(String[] args) throws Exception {
// Khởi tạo một đối tượng ServerSocket lắng nghe ở cổng 8083
ServerSocket serverSocket = new ServerSocket(8083);
// Tạo một bộ điều phối luồng với số lượng tối đa 10 luồng, tối thiểu 5 luồng
ExecutorService threadPool = Executors.newFixedThreadPool(10);
while (true) {
// Chấp nhận kết nối từ máy khách
Socket clientConnection = serverSocket.accept();
// Giao việc xử lý kết nối cho một luồng mới trong bộ điều phối luồng
threadPool.submit(() -> {
try {
// Lấy luồng đọc dữ liệu từ kết nối
InputStream dataReceiver = clientConnection.getInputStream();
// Chuẩn bị lưu trữ tệp tin vào thư mục đích
File destinationFolder = new File("D:" + File.separator + "upload");
if (!destinationFolder.exists()) {
destinationFolder.mkdirs();
}
File destinationFile = new File(destinationFolder, System.currentTimeMillis() + ".jpg");
FileOutputStream fileWriter = new FileOutputStream(destinationFile);
// Đọc dữ liệu từ luồng và lưu vào tệp tin
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = dataReceiver.read(buffer)) != -1) {
fileWriter.write(buffer, 0, bytesRead);
}
// Gửi phản hồi về máy khách
OutputStream responseSender = clientConnection.getOutputStream();
responseSender.write("Máy chủ phản hồi: Tải lên thành công!".getBytes());
// Đóng các luồng đã mở
fileWriter.close();
clientConnection.close();
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
}
Thử nghiệm
Chạy ứng dụng máy chủ trước sau đó chạy ứng dụng máy khách. Trên giao diện của máy khách, bạn sẽ thấy thông báo phản hồi từ máy chủ. Kiểm tra thư mụcupload trên ổ đĩa D:, bạn sẽ thấy tệp tin .jpg đã được tải lên.
Qua ví dụ trên, chúng ta đã mô phỏng việc tải lên tệp tin từ máy khách đến máy chủ sử dụng kỹ thuật đa luồng. Trong ví dụ này, FileInputStream và InputStream được sử dụng để đọc dữ liệu từ tệp tin và luồng mạng tương ứng, trong khi FileOutputStream và OutputStream dùng để ghi dữ liệu vào tệp tin và luồng mạng.