Lập trình

Lập trình mạng với java

Huy Erick

Trong bài viết này, chúng ta sẽ khám phá về lập trình mạng trong Java và tìm hiểu về một số lớp quan trọng trong gói java.net. Đồng thời, tôi sẽ hướng dẫn các bạn...

Trong bài viết này, chúng ta sẽ khám phá về lập trình mạng trong Java và tìm hiểu về một số lớp quan trọng trong gói java.net. Đồng thời, tôi sẽ hướng dẫn các bạn xây dựng ứng dụng Client-Server sử dụng Socket thông qua giao tiếp TCP và UDP.

Giới thiệu

Lập trình mạng là việc tạo ra những ứng dụng có khả năng làm việc với nhau thông qua môi trường mạng, chẳng hạn như Web, Mail, Skype, Zalo...

Lập trình socket trong Java cung cấp cách thức để chia sẻ dữ liệu giữa các thiết bị máy tính khác nhau.

Trước khi bắt đầu, hãy cùng tìm hiểu một số khái niệm quan trọng trong lập trình mạng ở Java.

Socket

Socket là một giao diện lập trình ứng dụng (API - Application Programming Interface).

Các Socket cho phép thiết lập các kênh giao tiếp mà hai đầu kênh được đánh dấu bằng hai cổng (port). Thông qua cổng này, một quá trình có thể nhận và gửi dữ liệu với các quá trình khác.

Port Number

Để thực hiện giao tiếp, một trong hai quá trình phải xác định số hiệu cổng (port number) của Socket mà nó sử dụng. Cổng giao tiếp đại diện cho một địa chỉ cụ thể trong hệ thống. Khi một quá trình được gán một số hiệu cổng, nó có thể nhận dữ liệu gửi đến cổng này từ các quá trình khác. Quá trình còn lại cũng được yêu cầu tạo ra một socket.

Số hiệu cổng (port number) được sử dụng để xác định các ứng dụng khác nhau. Nó hoạt động như một điểm kết nối giao tiếp giữa các ứng dụng.

Số hiệu cổng được kết hợp với địa chỉ IP để giao tiếp giữa hai ứng dụng.

Số hiệu cổng gán cho Socket phải duy nhất trên mỗi máy tính và có giá trị trong khoảng từ 0 đến 65535 (16 bit). Trong khoảng này:

  • Từ 0-1023: là cổng hệ thống (common hay well-known ports), được dành riêng cho các quá trình của hệ thống.
  • Từ 1024-49151: là cổng phải đăng ký (registered port). Các ứng dụng muốn sử dụng cổng này phải đăng ký với IANA (Internet Assigned Numbers Authority).
  • Từ 49152-65535: là cổng dùng riêng hay cổng động (dynamic hay private port). Người sử dụng có thể dùng cho các ứng dụng của mình mà không cần phải đăng ký.

Dưới đây là một số ví dụ về các cổng thường được sử dụng:

  • 21: dịch vụ FTP
  • 23: dịch vụ Telnet
  • 25: dịch vụ Email (SMTP)
  • 80: dịch vụ Web (HTTP)
  • 110: dịch vụ Email (POP)

IP Address

Ngoài số hiệu cổng, hai bên giao tiếp cần biết địa chỉ IP của nhau. Địa chỉ IP giúp phân biệt máy tính này với máy tính kia trên mạng TCP/IP. Trong khi số hiệu cổng dùng để phân biệt các quá trình khác nhau trên cùng một máy tính.

Địa chỉ IP (IP Address) là một số duy nhất được gán cho một nút trong mạng, ví dụ: 192.168.0.1. Nó bao gồm các số thập phân trong khoảng từ 0 đến 255.

Địa chỉ IP là một địa chỉ logic (logical address) có thể thay đổi.

MAC Address

Địa chỉ MAC (Media Access Control) là một phần của tầng liên kết dữ liệu trong mô hình 7 tầng OSI. Nó là một định danh duy nhất cho NIC (Network Interface Controller).

Mỗi máy tính có thể có nhiều NIC nhưng chỉ có duy nhất một địa chỉ MAC.

Protocol

Giao thức (Protocol) là một bộ các quy tắc cơ bản mà các ứng dụng phải tuân thủ để giao tiếp, ví dụ: giao thức TCP, FTP, Telnet, SMTP, POP...

Các chế độ giao tiếp

Xét kiến trúc của hệ thống mạng TCP/IP:

Tầng vận chuyển giúp chuyển tiếp thông điệp giữa các chương trình ứng dụng với nhau. Nó có thể hoạt động theo hai chế độ:

  • Giao tiếp có nối kết, nếu sử dụng giao thức TCP.
  • Hoặc giao tiếp không nối kết, nếu sử dụng giao thức UDP.

Socket là giao diện giữa chương trình ứng dụng và tầng vận chuyển. Nó cho phép ta chọn giao thức sử dụng ở tầng vận chuyển là TCP (Transmission Control Protocol) hoặc UDP (User Datagram Protocol) cho chương trình ứng dụng của mình.

So sánh TCP với UDP:

TCP (Transmission Control Protocol) UDP (User Datagram Protocol)
Giao thức hướng kết nối (connection-oriented protocol), tồn tại kênh giao tiếp ảo giữa hai bên giao tiếp. Giao thức không kết nối (connection-less protocol), không tồn tại kênh giao tiếp ảo giữa hai bên giao tiếp.
Dữ liệu được gửi đi theo chế độ bảo đảm: có kiểm tra lỗi, truyền lại gói tin lỗi hay mất, bảo đảm thứ tự đến của các gói tin... Dữ liệu được gửi đi theo chế độ không bảo đảm: không kiểm tra lỗi, không phát hiện gói tin lỗi hay mất, không bảo đảm thứ tự đến của các gói tin...
Dữ liệu chính xác, tốc độ truyền chậm. Dữ liệu có thể không chính xác, tốc độ truyền nhanh.
Thích hợp cho các ứng dụng cần độ chính xác cao như: truyền file, thông tin điều khiển... Thích hợp cho các ứng dụng không cần độ chính xác cao mà chỉ cần tốc độ nhanh như: truyền âm thanh, hình ảnh...

Một số lớp quan trọng trong gói java.net

Lớp URL

URL là viết tắt của Uniform Resource Locator và biểu diễn một tài nguyên trên Web, ví dụ như một trang Web hoặc thư mục FTP.

Một URL có thể được chia thành các phần như sau:

Lớp java.net.URL cung cấp các phương thức để truy cập các phần khác nhau của URL như sau:

  • public String getPath(): trả về path của URL đó.
  • public String getQuery(): trả về phần query của URL đó.
  • public String getAuthority(): trả về authority của URL đó.
  • public int getPort(): trả về port của URL đó.
  • public int getDefaultPort(): trả về port mặc định cho protocol của URL đó.
  • public String getProtocol(): trả về protocol của URL đó.
  • public String getHost(): trả về host của URL đó.
  • public String getFile(): trả về filename của URL đó.
  • public String getRef(): trả về phần reference của URL đó.
  • public URLConnection openConnection(): mở một kết nối tới URL, cho phép một client giao tiếp với tài nguyên.

Dưới đây là một ví dụ sử dụng lớp URL:

import java.io.IOException; import java.net.URL;  public class UrlExample {     public static void main(String[] args) {         try {             URL url = new URL("https://www.gpcoder.com:80/java/index.html?page=1&order=desc#java-core");             System.out.println("URL : " + url.toString());             System.out.println("protocol : " + url.getProtocol());             System.out.println("authority : " + url.getAuthority());             System.out.println("file name : " + url.getFile());             System.out.println("host : " + url.getHost());             System.out.println("path : " + url.getPath());             System.out.println("port : " + url.getPort());             System.out.println("default port : " + url.getDefaultPort());             System.out.println("query : " + url.getQuery());             System.out.println("ref : " + url.getRef());         } catch (IOException e) {             e.printStackTrace();         }     } }

Kết quả khi thực thi chương trình:

URL : https://www.gpcoder.com:80/java/index.html?page=1&order=desc#java-core protocol : https authority : www.gpcoder.com:80 file name : /java/index.html?page=1&order=desc host : www.gpcoder.com path : /java/index.html port : 80 default port : 443 query : page=1&order=desc ref : java-core

Lớp URLConnection

Phương thức openConnection() của lớp java.net.URL trả về một java.net.URLConnection. Đây là lớp trừu tượng mà các lớp con của nó đại diễn cho các kiểu kết nối URL đa dạng.

Ví dụ:

  • Nếu một URL có giao thức là HTTP, thì phương thức openConnection() trả về một đối tượng HttpURLConnection.
  • Nếu một URL biểu diễn một JAR file, thì phương thức openConnection() trả về một đối tượng JarURLConnection.

Một số phương thức quan trọng của lớp URLConnection:

  • Object getContent(): lấy nội dung của URL connection này.
  • Object getContent(Class[] classes): lấy nội dung của URL connection này.
  • String getContentEncoding(): trả về giá trị của trường content-encoding header.
  • int getContentLength(): trả về giá trị của trường content-length header.
  • String getContentType(): trả về giá trị của trường content-type header.
  • int getLastModified(): trả về giá trị của trường last-modified header.
  • long getExpiration(): trả về giá trị của trường expires header.
  • long getIfModifiedSince(): trả về giá trị của trường ifModifiedSince của đối tượng này.
  • public void setDoInput(boolean input): Truyền là true để biểu thị rằng connection sẽ được sử dụng cho input. Giá trị mặc định là true vì Client đọc từ một URLConnection.
  • public void setDoOutput(boolean output): Truyền là true để biểu thị rằng connection sẽ được sử dụng cho output. Giá trị mặc định là false vì nhiều kiểu URL không hỗ trợ ghi trên đó.
  • public InputStream getInputStream() throws IOException: trả về InputStream của URL connection để đọc từ nguồn.
  • public OutputStream getOutputStream() throws IOException: trả về OutputStream của URL connection để ghi từ nguồn.
  • public URL getURL(): trả về URL mà đối tượng URLConnection này được kết nối tới.

Dưới đây là một ví dụ sử dụng lớp URLConnection:

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection;  public class URLConnectionExample {     public static void main(String[] args) {         try {             URL url = new URL("https://www.w3schools.com/");             URLConnection urlConnection = url.openConnection();              BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));             StringBuilder sb = new StringBuilder();             String line;             while ((line = br.readLine()) != null) {                 sb.append(line + "\n");             }              System.out.println(sb.toString());         } catch (IOException e) {             e.printStackTrace();         }     } }

Kết quả khi thực thi chương trình:

  W3Schools Online Web Tutorials     
THE WORLD'S LARGEST WEB DEVELOPER SITE

Lớp InetAddress

Lớp Java InetAddress đại diện cho một địa chỉ IP. Lớp java.net.InetAddress cung cấp các phương thức để lấy IP của một máy chủ bất kỳ.

Lớp InetAddress có thể xử lý cả địa chỉ IPv4 và IPv6. InetAddress không có constructor, để tạo một đối tượng InetAddress, bạn phải sử dụng các phương thức Factory.

Một số phương thức của lớp InetAddress:

  • public String getHostName(): trả về tên máy chủ (host) của địa chỉ IP.
  • public String getHostAddress(): trả về địa chỉ IP dưới dạng chuỗi.

Dưới đây là một ví dụ sử dụng lớp InetAddress:

import java.net.InetAddress; import java.net.UnknownHostException;  public class InetAddressExample {     public static void main(String[] args) throws UnknownHostException {         InetAddress ip = InetAddress.getLocalHost();         System.out.println("Host Name: " + ip.getHostName());         System.out.println("IP Address: " + ip.getHostAddress());          ip = InetAddress.getByName("www.studytonight.com");         System.out.println("\nHost Name: " + ip.getHostName());         System.out.println("IP Address: " + ip.getHostAddress());          System.out.println("\nAll address of google: ");         InetAddress[] sw = InetAddress.getAllByName("www.google.com");         for (int i = 0; i  sw.length; i++) {             System.out.println(sw[i]);         }     } }

Kết quả khi thực thi chương trình:

Host Name: DESKTOP-6NRLLE7 IP Address: 192.168.101.2  Host Name: www.studytonight.com IP Address: 104.25.248.103  All address of google: www.google.com/64.233.187.147 www.google.com/64.233.187.105 www.google.com/64.233.187.104 www.google.com/64.233.187.106 www.google.com/64.233.187.103 www.google.com/64.233.187.99

Lớp Socket, ServerSocket, DatagramPacket, DatagramSocket và MulticastSocket

Để dễ hiểu, các lớp này sẽ được giới thiệu trong bài viết xây dựng ứng dụng Client-Server với Socket. Hãy tiếp tục theo dõi nhé.

Tài liệu tham khảo:

1