Bài số 3: Xây dựng ứng dụng Intranet với UDP Socket

Tương tự bài số 1 nhưng client/server trao đổi dữ liệu với UDP thay vì TCP. Các bước thực hiện như sau:

  • Bước 1: Xây dựng chương trình client và server
  • Bước 2: Vận hành chương trình
  • Bước 3: Bắt gói tin với tcpdump và phân tích

Bước 1: Xây dựng chương trình client và server

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

public class udpserver {

	public static void main(String[] args) throws Exception {
		int udp_port = 0;
		
		if (args.length !=1) {
			System.out.println("Usage: udpserver [udp port]");
			System.exit(0);
		}
		try {
			udp_port = Integer.parseInt(args[0]);
		} catch (Exception e) {
			System.out.println("Usage: udpserver [udp port]");
			System.exit(0);
		}
		
		DatagramSocket serverSocket = new DatagramSocket(udp_port); 
		byte[] receiveData = new byte[1024]; 
		byte[] sendData = new byte[1024]; 
		while(true) { 
			System.out.println("UDP Server is waiting for client data at port: " + udp_port);
			DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); 
			serverSocket.receive(receivePacket); 
			System.out.println("  - Received data from client: " + 
						receivePacket.getAddress().getHostAddress() + ":" + receivePacket.getPort());
			String sentence = new String(receivePacket.getData());
			System.out.println("  - Data: " + sentence);
			InetAddress IPAddress = receivePacket.getAddress(); 
			int port = receivePacket.getPort(); 
			String capitalizedSentence = sentence.toUpperCase();
			System.out.println("  - Send data to client: " + capitalizedSentence);
			sendData = capitalizedSentence.getBytes(); 
			DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port); 
			serverSocket.send(sendPacket);
			System.out.println("  - Finish working with client.\n\n");
		}
	}
}
			 

Chương trình phía client như sau:

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

public class udpclient {

	public static void main(String[] args) throws Exception {
		int server_port = 0;
		String server_ip = "";
		
		if (args.length !=2) {
			System.out.println("Usage: udpclient [server address] [server port]");
			System.exit(0);
		}
		try {
			server_port = Integer.parseInt(args[1]);
			server_ip = args[0];
		} catch (Exception e) {
			System.out.println("Usage: udpclient [server address] [server port]");
			System.exit(0);
		}
		
		System.out.print("Enter a sentence to send to server: ");
		BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in)); 
		DatagramSocket clientSocket = new DatagramSocket(); 
		InetAddress IPAddress = InetAddress.getByName(server_ip); 
		byte[] sendData = new byte[1024]; 
		byte[] receiveData = new byte[1024]; 
		String sentence = inFromUser.readLine(); 
		sendData = sentence.getBytes();
		DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9876);
		System.out.println("Sending data to server...");
		clientSocket.send(sendPacket); 
		DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); 
		System.out.println("Receiving data from server...");
		clientSocket.receive(receivePacket); 
		String modifiedSentence = new String(receivePacket.getData()); 
		System.out.println("Data received from server:" + modifiedSentence);
		clientSocket.close();
	}

}
			 

Bước 2: Vận hành chương trình

Dịch chương trình và đưa lên thư mục share để chạy udpserver trên các máy R4:

> java udpserver 9874
UDP Server is waiting for client data at port: 9876
- Received data from client: 192.168.2.1:52053
- Data: test from router r1
- Send data to client: TEST FROM ROUTER R1
- Finish working with client.

Chạy udpclient trên máy R1:

> java udpclient 192.168.4.2 9876
Enter a sentence to send to server: test from router r1

Sending data to server...
Receiving data from server...
Data received from server:TEST FROM ROUTER R1

Bước 3: Bắt gói tin với tcpdump và phân tích

Chạy tcpdump trên R1 để hiển thị các gói tin UDP:

> tcpdump -nX udp -i eth1 port 9876
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
1.	03:24:07.127895 IP 192.168.2.1.52053 > 192.168.4.2.9876: UDP, length 19
        0x0000:  4500 002f 0000 4000 4011 4908 c0a8 3864  		E../..@.@.I...8d
        0x0010:  c0a8 3801 cd95 2694 001b f1e2 7465 7374  		..8...&.....test
        0x0020:  2066 726f 6d20 726f 7574 6572 2072 31    		.from.router.r1

2.	03:24:07.137291 IP 192.168.4.2.9876 > 192.168.2.1.52053: UDP, length 1024
        0x0000:  4500 041c 0bb8 0000 8011 3963 c0a8 3801  		E.........9c..8.
        0x0010:  c0a8 3864 2694 acc8 0408 8d33 5445 5354  		..8d&......3TEST
        0x0020:  2046 524f 4d20 524f 5554 4552 2052 3100  		.FROM.ROUTER.R1.
        0x0030:  0000 0000 0000 0000 0000 0000 0000 0000 		 ................
        0x0040:  0000 0000 0000 0000 0000 0000 0000 0000  		................
			 

So sánh với trường hợp sử dụng TCP, truyền dữ liệu bằng UDP diễn ra đơn giản hơn rất nhiều. Không có các gói tin thực hiện thủ tục bắt tay, không có các gói tin xác nhận ACK. Toàn bộ phiên truyền dữ liệu chỉ gồm 2 gói tin gửi đi từ client lên server và gửi từ server về client. Lưu ý là do chương trình không xử lý chi tiết các thông số độ dài gói tin nên gói tin gửi từ client có độ dài 19 bytes (đúng bằng độ dài xâu client gửi lên server “test from router r1”). Gói tin gửi từ server về client có độ dài 1024. Các byte 0 được gán thêm vào sau xâu dữ liệu “TEST FROM ROUTER R1”.