Bài viết được lấy từ https://truongphuoc.wordpress.com/2024/07/18/javanet-p1-gioi-thieu-java-networking/
Lời dẫn
Trong thực tế, khi hai người muốn trao đổi thông tin với nhau, chúng ta có thể gọi điện, viết thư cho nhau. Trong mạng máy tính cũng thế, khi hai máy tính, thiết bị muốn trao đổi thông tin với nhau, chúng cũng có thể "gọi điện, viết thư" cho nhau được.
Trong bài viết này mình sẽ giới thiệu cách hai máy tính, thiết bị có thể "gọi điện" để trao đổi thông tin với nhau.
Cách hai người gọi điện cho nhau
Khi Anh gọi điện cho Em, hai người cần ít nhất những thứ sau:
- Anh và Em phải có thiết bị đầu cuối hay thiết bị liên lạc. Ở đây là chiếc điện thoại.
- Ít nhất một trong hai người Anh và Em phải biết số điện thoại của nhau.
- Người có số điện thoại gọi cho người còn lại.
- Đối phương nhấc máy.
- Hai người trao đổi tình cảm.
Trên đây là 5 thứ để Anh và Em trao đổi tình cảm qua điện thoại trong đời sống. Chúng ta hãy cùng xem, nếu Anh và Em là hai máy tính thì họ sẽ gọi điện trao đổi tình cảm với nhau thế nào.
Gói java net
Java net là một package trong java, nó cung cấp cho ta các class cần thiết để lập trình mạng. Chúng ta có thể coi nó là một cửa hàng điện thoại, tại đây chúng ta có thể mua điện thoại, mua sim,... Java net cũng thế, nó cung cấp cho ta những thứ cần thiết để ta có thể "mua" và tạo ra một "chiếc điện thoại" hoàn chỉnh.
Chiếc điện thoại
Khi gọi điện, điện thoại đóng vai trò là thiết bị đầu cuối hay điểm cuối (endpoint). Java net cung cấp cho chúng ta Socket và ServerSocket, đây là hai endpoint cho một cuộc "gọi điện" trên mạng.
Socket
Socket giống như một chiếc điện thoại nhưng nó chỉ có thể tạo cuộc gọi. Chúng ta có thể sử dụng method connect() để tạo một "cuộc gọi" đi.
ServerSocket
ServerSocket giống như một chiếc điện thoại nhưng chỉ có thể chấp nhận cuộc gọi. Chúng ta có thể sử dụng method accept() để chấp nhận một "cuộc gọi" tới.
TCP
Socket và ServerSocket kết hợp với nhau để tạo một kết nối TCP. Ngoài ra, chúng ta có thể tạo ra kết nối UDP bằng class DatagramSocket.
Về TCP, UDP và DatagramSocket có lẽ mình sẽ giới thiệu ở một bài viết khác, các bạn cùng đón đọc nha.
Số điện thoại
Trong TCP/IP, "số điện thoại" là sự kết hợp của IP Address và Port.
InetAddress
Đại diện cho một địa chỉ IP, ví dụ chúng ta muốn xem địa chỉ IP của google.com
InetAddress google = InetAddress.getByName("google.com");
System.out.println(google);
// google.com/142.251.130.14
InetSocketAddress
Đại diện cho một địa chỉ của Socket. Nó chính là "số điện thoại" của chúng ta. InetSocketAddress là duy nhất và được xác định bởi hai cấu thành là InetAddress và port
InetAddress google = InetAddress.getByName("google.com");
InetSocketAddress inetSocketAddress = new InetSocketAddress(google, 1234);
System.out.println(inetSocketAddress);
// google.com/142.251.130.14:1234
Gọi và nhấc máy
Đến đây chúng ta đã có hai chiếc điện thoại là Socket và ServerSocket, có số điện thoại là InetSocketAddress, có thể tạo cuộc gọi bằng method connect() và chấp nhận cuộc gọi bằng ***accept()***. Hãy cùng kết hợp tất cả mọi thứ với nhau như sau:
Gọi - Tạo cuộc gọi
import java.io.*;
import java.net.*; public class Client { public static void main(String[] args) throws IOException { Socket socket = null; try { socket = new Socket(); InetAddress localhost = InetAddress.getByName("localhost"); InetSocketAddress inetSocketAddress = new InetSocketAddress(localhost, 8080); socket.connect(inetSocketAddress); System.out.println("Client info: " + socket); // Client info: Socket[addr=localhost/127.0.0.1,port=8080,localport=57884] } finally { if (socket != null) { socket.close(); } } }
}
Chúng ta sử dụng Socket để tạo kết nối TCP tới địa chỉ localhost:8080.
Nhấc máy - Chấp nhận cuộc gọi
import java.io.*;
import java.net.*; public class Server { public static void main(String[] args) throws IOException { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(); InetAddress inetAddress = InetAddress.getByName("0.0.0.0"); SocketAddress socketAddress = new InetSocketAddress(inetAddress, 8080); serverSocket.bind(socketAddress); Socket clientSocket = serverSocket.accept(); System.out.println("Connected : " + clientSocket); // Connected to client: Socket[addr=/127.0.0.1,port=57884,localport=8080] } finally { if (serverSocket != null) { serverSocket.close(); } } }
}
Chúng ta gán (bind) cho ServerSocket lắng nghe kết nối TCP trên địa chỉ 0.0.0.0:8080. Địa chỉ 0.0.0.0 đại diện cho tất cả địa chỉ, có nghĩa là ServerSocket sẽ lắng nghe mọi kết nối TCP trên cổng 8080.
Khi có cuộc gọi tới, ServerSocket có thể chấp nhận cuộc gọi bằng accpet() .
Bài tập về nhà: Các bạn hãy nhìn và gõ đoạn code trên, chứ đừng copy,patse. Đoạn trên cũng ngắn không có dài gì cả. Việc tự viết khiến bạn phải chú ý tới từng dòng, từng câu lệnh và sẽ hiểu rõ hơn về bài viết. Lý tưởng nhất là các bạn có thể tự viết đoạn code của riêng mình, chỉ cần nhớ nó giống như việc gọi điện thoại thôi.
Trao đổi tình cảm
Để có thể trao đổi thông tin với nhau thông qua Socket và SocketServer, chúng ta cần phải sử dụng Java IO. Đây là một chủ đề dài, mình sẽ giới thiệu trong bài tiếp theo.
Kết luận
Hai chiếc máy tính có thể gọi điện cho nhau để trao đổi thông tin. Trong Java networking, package java net đóng vai trò như một cửa hàng điện thoại cung cấp điện thoại - Socket và ServerSocket, đồng thời cũng cung cấp số điện thoại: InetSocketAddress để chúng ta có thể tạo một cuộc gọi - kết nối TCP. Từ đó hai máy tính có thể trao đổi thông tin.
Việc trao đổi thông tin thông qua Socket và SocketServer phải sử dụng Java IO. Đây là một chủ đề dài và chúng ta sẽ tìm hiểu trong bài tiếp theo.
Hỏi và đáp
1. Package Java net có từ Java version mấy?
Package Java net có ngay trong phiên bản đầu tiên của java (JDK 1.0) vào năm 1996.
2. Socket trong những ngôn ngữ khác?
Socket là một khái niệm được hệ điều hành (OS) cung cấp và quản lý. Hệ điều hành cung cấp API cho những ngôn ngữ lập trình có thể thao tác với nó (chứ không phải là khái niệm riêng của Java đâu nha). Cách sử dụng Socket ở một vài ngôn ngữ khác nhau:
2.1 Python
import socket # client
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 12345)) # server
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 12345))
server_socket.listen()
2.2 C#
C# sử dụng tên khác là TcpClient cho Socket và TcpListener cho ServerSocket
using System;
using System.Net;
using System.Net.Sockets; class Client { static void Main() { TcpClient client = new TcpClient("localhost", 12345); }
} class Server { static void Main() { TcpListener server = new TcpListener(IPAddress.Any, 12345); server.Start(); }
}
2.3 JavaScript
const net = require('net'); // client
const client = new net.Socket();
client.connect(12345, 'localhost', () => {...}); // server
const server = net.createServer((socket) => {...});
server.listen(12345, 'localhost', () => { console.log('Server is listening on port 12345');
});
3. Port trong máy tính là gì?
Để hiểu được ý nghĩa của port, ta hãy đến với thế giới mà không có port: Khi đó ta muốn chạy hai chương trình sẽ có chút rắc rối, ví dụ ta chạy hai chương trình tính toán, một chương trình sẽ thực hiện phép cộng còn một chương trình sẽ thực hiện phép trừ. Cả hai chương trình cùng sử dụng khái niệm SocketServer hay TcpListener,.... tức là lắng nghe kết nối TCP tới. Khi có một kết nối TCP thì cả hai chương trình đều cần phải chạy, điều này gây lãng phí tài nguyên vì khi có kết nối TCP tới nó chỉ muốn kết nối tới một chương trình mà thôi, đồng thời cũng xảy ra xung đột (Trong trường hợp này thì máy tính sẽ trả về phép cộng hay trừ hai số?).
Bằng cách sử dụng port ta có thể viết nhiều phần mềm mạng, nó chỉ lắng nghe trên một cổng cố định, kết nối tới sẽ trỏ thẳng tới cổng ứng dụng đang lắng nghe, không xảy ra lãng phí xung đột gì cả, rất tiện phải không ạ.
4. Có cần hiểu về các kết nối dưới tầng ứng dụng không?
Trong thực tế khi ta lập trình, trừ khi bạn là một nhà lập trình mạng thì dường như chúng ta không bao giờ phải đụng đến kết nối của các tầng bên dưới tầng ứng dụng (Application Layer), thậm chí bạn chỉ sử dụng framework còn không biết tầng ứng dụng luôn: HTTP xử lý thế nào, Servlet chỉ là khái niệm để đi học còn đi làm thì không dùng tới.v.v.
Nhưng chúng ta là một lập trình viên, đây là những kiến thức cơ bản, chúng ta cần biết mọi thứ hoạt động thế nào, ít nhất là hiểu về những khái niệm cơ bản. Tin mình đi, các bạn không cần phải biết quá sâu nếu không làm mảng về mạng, nhưng nếu các bạn có thời gian và đọc hiểu những bài viết về tầng bên dưới, bạn sẽ thấy rằng những điều bạn phải nhớ: như các method trong HTTP, rồi xử lý request, response thế nào, vòng đời servlet,... mọi thứ đều là điều hiển nhiên à, không cần phải nhớ gì hết vì nó phải như thế mà.
Link bài viết gốc: https://truongphuoc.wordpress.com/2024/07/18/javanet-p1-gioi-thieu-java-networking/