Lập trình mạng trong Java: Giao tiếp UDP và TCP

1. Giới thiệu về lập trình mạng

1.1 Tổng quan lập trình mạng

1.2 Ba yếu tố cơ bản của lập trình mạng

1.3 Địa chỉ IP

Sử dụng trong dòng lệnh:

1.4 Sử dụng lớp InetAddress

Ví dụ mã nguồn:

import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetAddressExample {
    public static void main(String[] args) throws UnknownHostException {
        // Lấy địa chỉ IP từ tên máy hoặc địa chỉ IP
        InetAddress addr = InetAddress.getByName("192.168.0.105");

        // Lấy tên máy chủ
        String hostname = addr.getHostName();
        System.out.println(hostname);

        // Lấy địa chỉ IP dạng chuỗi
        String ipAddress = addr.getHostAddress();
        System.out.println(ipAddress);
    }
}

Kết quả chạy chương trình:

Ví dụ bổ sung:

import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetAddressTest {
    public static void main(String[] args) throws UnknownHostException {
        System.out.println(InetAddress.getLocalHost());
        System.out.println(InetAddress.getLocalHost().getHostName());
        System.out.println(InetAddress.getLocalHost().getHostAddress());
        System.out.println(InetAddress.getByName("192.168.3.11"));
        System.out.println(InetAddress.getByName("192.168.3.11").getHostName());
        System.out.println(InetAddress.getByName("192.168.3.11").getHostAddress());
        System.out.println(InetAddress.getByName("LAPTOP-VEKHRDDR"));
        System.out.println(InetAddress.getByName("LAPTOP-VEKHRDDR").getHostName());
        System.out.println(InetAddress.getByName("LAPTOP-VEKHRDDR").getHostAddress());
    }
}

1.5 Cổng kết nối

1.6 Giao thức truyền thông

Bắt tay ba bước (Three-way handshake)

2. Chương trình giao tiếp UDP

2.1 Nguyên lý giao tiếp UDP

2.2 Gửi dữ liệu qua UDP

Ví dụ mã nguồn - Tạo phía gửi:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UDPSender {
    public static void main(String[] args) throws IOException {
        // Tạo socket UDP
        DatagramSocket socket = new DatagramSocket();
        
        // Chuẩn bị dữ liệu để gửi
        byte[] data = "Xin chào UDP, tôi đến rồi".getBytes();
        InetAddress targetAddr = InetAddress.getByName("192.168.0.105");
        int targetPort = 10086;
        
        // Đóng gói dữ liệu
        DatagramPacket packet = new DatagramPacket(data, data.length, targetAddr, targetPort);
        
        // Gửi dữ liệu
        socket.send(packet);
        
        // Đóng socket
        socket.close();
    }
}

Kết quả: Không có đầu ra vì chưa có bên nhận

2.3 Nhận dữ liệu qua UDP

Ví dụ mã nguồn - Tạo phía nhận:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UDPReceiver {
    public static void main(String[] args) throws IOException {
        // Tạo socket nhận trên cổng cụ thể
        DatagramSocket socket = new DatagramSocket(10086);
        
        // Tạo bộ đệm để nhận dữ liệu
        byte[] buffer = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
        
        // Nhận dữ liệu
        socket.receive(packet);
        
        // Xử lý dữ liệu nhận được
        String receivedData = new String(packet.getData(), 0, packet.getLength());
        System.out.println("Dữ liệu nhận được: " + receivedData);
        
        String senderIP = packet.getAddress().getHostAddress();
        System.out.println("Nhận tin nhắn từ: " + senderIP);
        
        // Đóng socket
        socket.close();
    }
}

Kết quả: Chạy bên nhận trước, sau đó bên gửi

2.4 Bài tập giao tiếp UDP

Ví dụ mã nguồn:

Phía gửi UDP:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UDPSendExercise {
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket();
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        
        String inputLine;
        while ((inputLine = reader.readLine()) != null) {
            if ("886".equals(inputLine)) {
                break;
            }
            
            byte[] message = inputLine.getBytes();
            DatagramPacket packet = new DatagramPacket(message, message.length, 
                                                     InetAddress.getByName("192.168.0.105"), 12345);
            socket.send(packet);
        }
        
        socket.close();
    }
}

Phía nhận UDP:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UDPReceiveExercise {
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket(12345);
        
        while (true) {
            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
            
            socket.receive(packet);
            String receivedMsg = new String(packet.getData(), 0, packet.getLength());
            System.out.println("Nhận được: " + receivedMsg);
        }
    }
}

3. Chương trình giao tiếp TCP

3.1 Nguyên lý giao tiếp TCP

3.2 Gửi dữ liệu qua TCP

Ví dụ mã nguồn:

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class TCPSender {
    public static void main(String[] args) throws IOException {
        // Kết nối đến máy chủ
        Socket socket = new Socket("192.168.0.105", 1000);
        
        // Gửi dữ liệu
        OutputStream output = socket.getOutputStream();
        output.write("Chào mừng TCP, tôi đến đây".getBytes());
        
        // Đóng kết nối
        socket.close();
    }
}

3.3 Nhận dữ liệu qua TCP

Ví dụ mã nguồn:

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPReceiver {
    public static void main(String[] args) throws IOException {
        // Tạo server socket lắng nghe trên cổng
        ServerSocket serverSocket = new ServerSocket(10000);
        
        // Chấp nhận kết nối từ client
        Socket clientSocket = serverSocket.accept();
        
        // Nhận dữ liệu
        InputStream input = clientSocket.getInputStream();
        byte[] buffer = new byte[1024];
        int bytesRead = input.read(buffer);
        
        System.out.println("Dữ liệu nhận được: " + new String(buffer, 0, bytesRead));
        
        // Đóng kết nối
        serverSocket.close();
    }
}

3.4 Bài tập giao tiếp TCP

3.4.1 Bài tập 1: Gửi dữ liệu và nhận phản hồi

Tạo client:

import java.io.*;
import java.net.Socket;

public class TCPClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("192.168.0.105", 1000);
        
        // Gửi dữ liệu
        OutputStream output = socket.getOutputStream();
        output.write("xin chao tcp toi day roi".getBytes());
        
        // Nhận phản hồi
        InputStream input = socket.getInputStream();
        byte[] responseBuffer = new byte[1024];
        int responseLength = input.read(responseBuffer);
        String response = new String(responseBuffer, 0, responseLength);
        System.out.println("Client nhận được: " + response);
        
        socket.close();
    }
}

Tạo server:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(1000);
        Socket clientSocket = serverSocket.accept();
        
        // Nhận dữ liệu từ client
        InputStream input = clientSocket.getInputStream();
        byte[] requestData = new byte[1024];
        int requestLength = input.read(requestData);
        String request = new String(requestData, 0, requestLength);
        System.out.println("Server nhận được: " + request);
        
        // Gửi phản hồi
        OutputStream output = clientSocket.getOutputStream();
        output.write("Dữ liệu đã nhận thành công".getBytes());
        
        serverSocket.close();
    }
}

3.4.2 Bài tập 2: Nhập dữ liệu từ bàn phím

Tạo client:

import java.io.*;
import java.net.Socket;

public class TCPKeyboardClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("192.168.0.105", 10000);
        
        BufferedReader keyboardInput = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
        
        String userInput;
        while ((userInput = keyboardInput.readLine()) != null) {
            if ("886".equals(userInput)) {
                break;
            }
            writer.println(userInput);
        }
        
        socket.close();
    }
}

Tạo server:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPKeyboardServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10000);
        Socket clientSocket = serverSocket.accept();
        
        BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        String receivedLine;
        
        while ((receivedLine = reader.readLine()) != null) {
            System.out.println("Nhận được: " + receivedLine);
        }
        
        serverSocket.close();
    }
}

3.4.3 Bài tập 3: Ghi dữ liệu vào file văn bản

Tạo client (giống bài tập 2):

import java.io.*;
import java.net.Socket;

public class TCPFileWriteClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("192.168.0.105", 10000);
        
        BufferedReader keyboardReader = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter socketWriter = new PrintWriter(socket.getOutputStream(), true);
        
        String lineInput;
        while ((lineInput = keyboardReader.readLine()) != null) {
            if ("886".equals(lineInput)) {
                break;
            }
            socketWriter.println(lineInput);
        }
        
        socket.close();
    }
}

Tạo server:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPFileWriteServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10000);
        Socket clientSocket = serverSocket.accept();
        
        BufferedReader socketReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        PrintWriter fileWriter = new PrintWriter(new FileWriter("output.txt"));
        
        String lineReceived;
        while ((lineReceived = socketReader.readLine()) != null) {
            fileWriter.println(lineReceived);
        }
        
        fileWriter.close();
        serverSocket.close();
    }
}

3.4.4 Bài tập 4: Gửi nội dung từ file

Tạo client:

import java.io.*;
import java.net.Socket;

public class TCPFileSendClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("192.168.0.105", 10000);
        
        BufferedReader fileReader = new BufferedReader(new FileReader("source.txt"));
        PrintWriter socketWriter = new PrintWriter(socket.getOutputStream(), true);
        
        String fileLine;
        while ((fileLine = fileReader.readLine()) != null) {
            socketWriter.println(fileLine);
        }
        
        fileReader.close();
        socket.close();
    }
}

Tạo server (giống bài tập 3):

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPFileReceiveServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10000);
        Socket clientSocket = serverSocket.accept();
        
        BufferedReader socketReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        PrintWriter fileWriter = new PrintWriter(new FileWriter("copied.txt"));
        
        String receivedLine;
        while ((receivedLine = socketReader.readLine()) != null) {
            fileWriter.println(receivedLine);
        }
        
        fileWriter.close();
        serverSocket.close();
    }
}

3.4.5 Bài tập 5: Thêm phản hồi từ server

Tạo client:

import java.io.*;
import java.net.Socket;

public class TCPFeedbackClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("192.168.0.105", 10000);
        
        BufferedReader fileReader = new BufferedReader(new FileReader("source.txt"));
        PrintWriter socketWriter = new PrintWriter(socket.getOutputStream(), true);
        
        String fileContent;
        while ((fileContent = fileReader.readLine()) != null) {
            socketWriter.println(fileContent);
        }
        
        // Thông báo kết thúc gửi dữ liệu
        socket.shutdownOutput();
        
        // Nhận phản hồi từ server
        BufferedReader responseReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String serverResponse = responseReader.readLine();
        System.out.println("Phản hồi từ server: " + serverResponse);
        
        fileReader.close();
        socket.close();
    }
}

Tạo server:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPFeedbackServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10000);
        Socket clientSocket = serverSocket.accept();
        
        BufferedReader socketReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        PrintWriter fileWriter = new PrintWriter(new FileWriter("copied_with_feedback.txt"));
        
        String receivedData;
        while ((receivedData = socketReader.readLine()) != null) {
            fileWriter.println(receivedData);
        }
        
        // Gửi phản hồi cho client
        PrintWriter responseWriter = new PrintWriter(clientSocket.getOutputStream(), true);
        responseWriter.println("Tải lên file thành công!");
        
        fileWriter.close();
        serverSocket.close();
    }
}

3.4.6 Bài tập 6: Xử lý đa client với đa luồng

Tạo client (giống bài tập 5):

import java.io.*;
import java.net.Socket;

public class TCPMultiClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("192.168.0.105", 10000);
        
        BufferedReader fileReader = new BufferedReader(new FileReader("source.txt"));
        PrintWriter socketWriter = new PrintWriter(socket.getOutputStream(), true);
        
        String lineFromFile;
        while ((lineFromFile = fileReader.readLine()) != null) {
            socketWriter.println(lineFromFile);
        }
        
        socket.shutdownOutput();
        
        BufferedReader feedbackReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String serverMessage = feedbackReader.readLine();
        System.out.println("Server trả lời: " + serverMessage);
        
        fileReader.close();
        socket.close();
    }
}

Tạo server:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPMultiServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10000);
        
        while (true) {
            Socket clientSocket = serverSocket.accept();
            new Thread(new ClientHandler(clientSocket)).start();
        }
    }
}

Tạo lớp xử lý client:

import java.io.*;
import java.net.Socket;

public class ClientHandler implements Runnable {
    private Socket clientSocket;
    
    public ClientHandler(Socket socket) {
        this.clientSocket = socket;
    }
    
    @Override
    public void run() {
        try {
            BufferedReader inputReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            
            // Tạo tên file duy nhất
            int fileCounter = 0;
            File outputFile = new File("copy_" + fileCounter + ".txt");
            while (outputFile.exists()) {
                fileCounter++;
                outputFile = new File("copy_" + fileCounter + ".txt");
            }
            
            PrintWriter fileWriter = new PrintWriter(new FileWriter(outputFile));
            
            String lineData;
            while ((lineData = inputReader.readLine()) != null) {
                fileWriter.println(lineData);
            }
            
            PrintWriter responseWriter = new PrintWriter(clientSocket.getOutputStream(), true);
            responseWriter.println("Upload file hoàn tất!");
            
            fileWriter.close();
            clientSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Thẻ: Java network-programming UDP TCP socket-programming

Đăng vào ngày 9 tháng 10 lúc 01:17