Thuật ngữ lập trình mạng với java đề cập đến việc viết các chương trình thực hiện trên nhiều thiết bị (máy tính), trong đó các thiết bị được kết nối với nhau.
Gói java.net của J2SE APIs chứa một tập hợp các lớp và giao tiếp cung cấp giao thức truyền thông ở mức độ thấp.
Gói java.net cung cấp hỗ trợ cho hai giao thức mạng phổ biến sau:
- TCP - TCP là viết tắt của Transmission Control Protocol. TCP thường được sử dụng qua giao thức Internet (Internet Protocol), được gọi là TCP/IP. Giao thức này cho phép giao tiếp tin cậy giữa hai ứng dụng.
- UDP - UDP là viết tắt của User Datagram Protocol, một giao thức cho phép truyền dữ liệu giữa các ứng dụng. Giao thức này không kiểm tra đến việc gói tin đã được gửi hay chưa, nên đây là giao tiếp không tin cậy giữa hai hoặc nhiều ứng dụng.
TCP và UDP là các giao thức cốt lõi của việc kết nối các thiết bị công nghệ với nhau. Ngoài ra, trong việc lập trình mạng với java chúng ta có thể sử dụng FTP, công nghệ J2EE...
Nội dung chính
Lập trình Socket
Socket cung cấp cơ chế truyền thông giữa hai máy tính sử dụng TCP. Một máy khách tạo ra socket để kết nối đến với máy chủ.
Lớp java.net.Socket đại diện cho một socket, và lớp java.net.ServerSocket cung cấp một cơ chế cho chương trình máy chủ để lắng nghe khách hàng và thiết lập kết nối với chúng.
Các bước thiết lập kết nối TCP giữa hai máy tính sử dụng socket:
- Máy chủ khởi tạo một đối tượng ServerSocket với một cổng giao tiếp (port).
- Máy chủ gọi phương thức accept() của lớp ServerSocket. Phương pháp này đợi cho đến khi một máy khách kết nối đến máy chủ trên cổng đã cho.
- Trong khi máy chủ đang chờ đợi, một máy khách khởi tạo đối tượng Socket, xác định tên máy chủ (IP hoặc domain) và số cổng để kết nối.
- Đối tượng socket của máy khách cố gắng kết nối máy khách tới máy chủ đã chỉ định và số cổng. Nếu truyền thông được thiết lập, máy khách bây giờ có một đối tượng socket có khả năng giao tiếp với máy chủ.
- Ở phía máy chủ, phương thức accept() trả về một tham chiếu đến một socket mới trên máy chủ được kết nối với socket của máy khách.
Sau khi kết nối được thiết lập, máy chủ và máy khách có thể truyền và nhận thông tin thông qua OutputStream và InputStream.
Lớp ServerSocket
Lớp java.net.ServerSocket được sử dụng bởi các ứng dụng máy chủ để tạo ra một một cổng và lắng nghe các yêu cầu của máy khách.
Các Constructor của lớp ServerSocket
No. | Constructor & Mô tả |
---|---|
1 | public ServerSocket (port int) throws IOException Cố gắng tạo một ServerSocket bị ràng buộc vào port được chỉ định. Một ngoại lệ xảy ra nếu port đã bị ràng buộc bởi một ứng dụng khác. |
2 | public ServerSocket(int port, int backlog) throws IOException Tương tự như hàm tạo trước đó, tham số backlog xác định có bao nhiêu máy khách đến để lưu trữ trong một hàng đợi. |
3 | public ServerSocket(int port, int backlog, InetAddress address) throws IOException Tương tự như constructor trước đó, tham số InetAddress chỉ định địa chỉ IP cục bộ để ràng buộc. InetAddress được sử dụng cho các máy chủ có thể có nhiều địa chỉ IP, cho phép máy chủ xác định địa chỉ IP nào để chấp nhận yêu cầu của máy khách. |
4 | public ServerSocket() throws IOException Tạo ra một ServerSocket không kết nối. Khi sử dụng Constructor này, sử dụng phương thức bind() khi bạn đã sẵn sàng để ràng buộc socket của máy chủ. |
Nếu Constructor ServerSocket không ném một ngoại lệ, có nghĩa là bạn đã khởi tạo thành công ServerSocket với cổng được chỉ định và đã sẵn sàng cho các yêu cầu của máy khách.
Các phương thức của lớp ServerSocket
No. | Phương thức & Mô tả |
---|---|
1 | public int getLocalPort() Trả về cổng mà socket của máy chủ lắng nghe. Phương thức này rất hữu ích nếu bạn truyền 0 như là số cổng trong một constructor và để cho máy chủ tìm thấy một cổng cho bạn. |
2 | public Socket accept() throws IOException Chờ cho một khách hàng đến. Phương thức này ngăn chặn cho đến khi một máy trạm kết nối đến máy chủ trên cổng được chỉ định hoặc socket timeout, giả sử rằng giá trị thời gian đã được thiết lập bằng phương thức setSoTimeout (). Nếu không, phương thức này sẽ khóa lại vô thời hạn. |
3 | public void setSoTimeout(int timeout) Thiết lập giá trị thời gian chờ cho bao lâu socket của máy chủ chờ khách hàng trong suốt quá trình chấp nhận (). |
4 | public void bind(SocketAddress host, int backlog) Liên kết socket tới máy chủ và cổng được chỉ định trong đối tượng SocketAddress. Sử dụng phương thức này nếu bạn đã tạo ra các ServerSocket bằng cách sử dụng nhà xây dựng không có đối số. |
Khi ServerSocket gọi accept(), phương thức này sẽ không return cho đến khi một client kết nối đến. Sau khi máy khách (client) kết nối, ServerSocket tạo một Socket mới trên một cổng không xác định và trả về một tham chiếu đến Socket mới này. Hiện kết nối TCP giữa máy khách và máy chủ và có thể truyền tin.
Lớp Socket
Lớp java.net.Socket đại diện cho socket mà cả máy khách và máy chủ sử dụng để liên lạc với nhau. Máy khách nhận được một đối tượng Socket bằng cách khởi tạo một, trong khi máy chủ lấy một đối tượng Socket từ giá trị trả về của phương thức accept().
Các Constructor của lớp Socket
Lớp Socket có năm Constructor mà một máy khách sử dụng để kết nối với một máy chủ như sau:
No. | Constructor & Mô tả |
---|---|
1 | public Socket(String host, int port) throws UnknownHostException, IOException. Constructor này cố gắng để kết nối với máy chủ được chỉ định tại cổng được chỉ định. Nếu Constructor này không ném một ngoại lệ, kết nối thành công và máy khách được kết nối với máy chủ. |
2 | public Socket(String host, int port) throws UnknownHostException, IOException. Constructor này giống hệt với hàm tạo trước đó, ngoại trừ việc máy chủ được biểu hiện bởi một đối tượng InetAddress. |
3 | public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException. Kết nối đến máy chủ và cổng được chỉ định, tạo một socket trên máy chủ cục bộ tại địa chỉ và cổng được chỉ định. |
4 | public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException. Constructor này giống hệt với constructor trước đó, ngoại trừ máy chủ được biểu hiện bởi một đối tượng InetAddress thay vì một String. |
5 | public Socket() Tạo một socket không liên lạc. Sử dụng phương thức connect() để kết nối socket này với máy chủ. |
Các phương thức của lớp Socket
Một số phương thức hay sử dụng trong lớp Socket được liệt kê ở đây. Lưu ý rằng cả máy khách lẫn máy chủ đều có một đối tượng Socket, do đó các phương thức này có thể được gọi bởi cả máy khách và máy chủ.
No. | Phương thức & Mô tả |
---|---|
1 | public void connect(SocketAddress host, int timeout) throws IOException Phương thức này kết nối socket với máy chủ được chỉ định. Phương thức này là cần thiết chỉ khi bạn khởi tạo Socket bằng cách sử dụng Constructor không có đối số. |
2 | public InetAddress getInetAddress() Phương thức này trả về địa chỉ của máy tính khác mà socket này được kết nối. |
3 | public int getPort() Trả về cổng mà socket bị ràng buộc trên máy remote. |
4 | public int getLocalPort() Trả về cổng mà socket bị ràng buộc trên máy local. |
5 | public SocketAddress getRemoteSocketAddress() Trả về địa chỉ của socket từ xa. |
6 | public InputStream getInputStream() throws IOException Trả về input stream của socket. Input stream được kết nối với output stream của socket remote. |
7 | public OutputStream getOutputStream() throws IOException Trả về dòng đầu ra của socket. Output stream được kết nối với input stream của socket remote. |
8 | public void close() throws IOException Đóng socket, làm cho đối tượng Socket này không còn có khả năng kết nối về với bất kỳ máy chủ nào. |
Các phương thứ của lớp InetAddress
Lớp InetAddress đại diện cho một địa chỉ giao thức Internet (IP). Dưới đây là những phương thức hữu ích mà bạn sẽ cần trong khi làm chương trình socket:
No. | Phương thức & Mô tả |
---|---|
1 | static InetAddress getByAddress(byte[] addr) Trả về đối tượng InetAddress với địa chỉ IP. |
2 | static InetAddress getByAddress(String host, byte[] addr) Tạo một InetAddress dựa trên tên máy chủ lưu trữ và địa chỉ IP. |
3 | static InetAddress getByName(String host) Xác định địa chỉ IP của máy chủ, với tên của máy chủ lưu trữ. |
4 | String getHostAddress() Trả về chuỗi địa chỉ IP trong phần trình bày văn bản. |
5 | String getHostName() Lấy tên máy chủ cho địa chỉ IP này. |
6 | static InetAddress InetAddress getLocalHost() Trả về máy chủ local. |
7 | String toString() Chuyển địa chỉ IP này sang một chuỗi. |
Ví dụ về lập trình socket
Ví dụ về Socket Client
ClientExample sau đây là một chương trình client kết nối đến một server bằng cách sử dụng một socket và gửi một lời chào, và sau đó chờ đợi cho một đáp ứng từ máy chủ.
package vn.kienthuclaptrinh.client; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; public class ClientExample { /** * main * * @author kienthuclaptrinh.net * @param args : server name and server port */ public static void main(String[] args) { String serverName = args[0]; int port = Integer.parseInt(args[1]); try { System.out.println("Connecting to " + serverName + " on port " + port); Socket client = new Socket(serverName, port); System.out.println("Just connected to " + client.getRemoteSocketAddress()); OutputStream outToServer = client.getOutputStream(); DataOutputStream out = new DataOutputStream(outToServer); out.writeUTF("Hello from " + client.getLocalSocketAddress()); InputStream inFromServer = client.getInputStream(); DataInputStream in = new DataInputStream(inFromServer); System.out.println("Server says " + in.readUTF()); client.close(); } catch (IOException e) { e.printStackTrace(); } } }
Ví dụ về Socket Server
Chương trình ServerExample sau đây là một ví dụ về một ứng dụng server sử dụng lớp Socket để lắng nghe cho các client trên một số cổng xác định bởi một đối số dòng lệnh.
package vn.kienthuclaptrinh.server; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketTimeoutException; public class ServerExample extends Thread { private ServerSocket serverSocket; public ServerExample(int port) throws IOException { serverSocket = new ServerSocket(port); serverSocket.setSoTimeout(30000); } public void run() { while (true) { try { System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "..."); Socket server = serverSocket.accept(); System.out.println("Just connected to " + server.getRemoteSocketAddress()); DataInputStream in = new DataInputStream(server.getInputStream()); System.out.println(in.readUTF()); DataOutputStream out = new DataOutputStream( server.getOutputStream()); out.writeUTF("Thank you for connecting to " + server.getLocalSocketAddress() + "\nGoodbye!"); server.close(); } catch (SocketTimeoutException s) { System.out.println("Socket timed out!"); break; } catch (IOException e) { e.printStackTrace(); break; } } } /** * main * * @author kienthuclaptrinh.net * @param args */ public static void main(String[] args) { int port = Integer.parseInt(args[0]); try { Thread t = new ServerExample(port); t.start(); } catch (IOException e) { e.printStackTrace(); } } }
Run ứng dụng
Từ eclipse export ra các file jar như sau:
Run 2 file server.jar và client.jar trên commnad line ta được kết quả như sau:
Run server.jar: java -jar server.jar 6677
Run server.jar: java -jar server.jar [serverIP] 6677