Cách tạo một ứng dụng mạng trong Java (với Hình ảnh)

Mục lục:

Cách tạo một ứng dụng mạng trong Java (với Hình ảnh)
Cách tạo một ứng dụng mạng trong Java (với Hình ảnh)

Video: Cách tạo một ứng dụng mạng trong Java (với Hình ảnh)

Video: Cách tạo một ứng dụng mạng trong Java (với Hình ảnh)
Video: Cách chụp ảnh màn hình Android đơn giản mà không cài ứng dụng phụ trợ 2024, Tháng tư
Anonim

Viết mã thực thi trên một thiết bị nhất định là rất hài lòng. Tuy nhiên, viết mã thực thi trên một số thiết bị giao tiếp với nhau chỉ đơn giản là khẳng định sự sống. Bài viết này sẽ hướng dẫn bạn cách kết nối và trao đổi tin nhắn qua mạng bằng giao thức điều khiển truyền (TCP).

Trong bài viết này, bạn sẽ thiết lập một ứng dụng sẽ kết nối máy tính của bạn với chính nó và về cơ bản, làm cho nó trở nên điên rồ - nói chuyện với chính nó. Bạn cũng sẽ tìm hiểu sự khác biệt giữa hai luồng được sử dụng rộng rãi nhất cho mạng trong Java và cách chúng hoạt động.

Luồng dữ liệu và đối tượng

Trước khi đi sâu vào mã, sự khác biệt giữa hai luồng được sử dụng trong bài viết cần được phân biệt.

Luồng dữ liệu

Luồng dữ liệu xử lý các kiểu và chuỗi dữ liệu nguyên thủy. Dữ liệu được gửi qua các luồng dữ liệu cần phải được tuần tự hóa và giải mã hóa theo cách thủ công, điều này khiến việc truyền dữ liệu phức tạp trở nên khó khăn hơn. Tuy nhiên, các luồng dữ liệu có thể giao tiếp với máy chủ và máy khách được viết bằng các ngôn ngữ khác ngoài Java. Luồng thô tương tự như luồng dữ liệu ở khía cạnh đó, nhưng luồng dữ liệu đảm bảo dữ liệu được định dạng theo cách độc lập với nền tảng, điều này có lợi vì cả hai bên đều có thể đọc dữ liệu đã gửi.

Luồng đối tượng

Các luồng đối tượng xử lý các kiểu dữ liệu nguyên thủy và các đối tượng triển khai

Serializable

giao diện. Dữ liệu được gửi qua các luồng đối tượng được tự động tuần tự hóa và giải mã hóa, giúp truyền dữ liệu phức tạp dễ dàng hơn. Tuy nhiên, luồng đối tượng chỉ có thể giao tiếp với máy chủ và máy khách được viết bằng Java. Cũng,

ObjectOutputStream

khi khởi tạo, sẽ gửi một tiêu đề đến

InputStream

của bên kia, khi khởi tạo, chặn thực thi cho đến khi nhận được tiêu đề.

Các bước

Tạo ứng dụng mạng trong Java Step1
Tạo ứng dụng mạng trong Java Step1

Bước 1. Tạo một lớp học

Tạo một lớp và đặt tên theo cách bạn muốn. Trong bài viết này, nó sẽ được đặt tên là

NetworkAppExample

lớp công khai NetworkAppExample {}

Tạo ứng dụng mạng trong Java Step2
Tạo ứng dụng mạng trong Java Step2

Bước 2. Tạo một phương thức chính

Tạo một phương thức chính và khai báo nó có thể đưa ra các ngoại lệ

Ngoại lệ

loại và bất kỳ lớp con nào của nó - tất cả các ngoại lệ. Đây được coi là một thực hành không tốt, nhưng có thể chấp nhận được đối với các ví dụ barebone.

public class NetworkAppExample {public static void main (String args) ném Exception {}}

Tạo ứng dụng mạng trong Java Step3
Tạo ứng dụng mạng trong Java Step3

Bước 3. Khai báo địa chỉ máy chủ

Ví dụ này sẽ sử dụng địa chỉ máy chủ cục bộ và số cổng tùy ý. Số cổng phải nằm trong dải từ 0 đến 65535 (bao gồm cả). Tuy nhiên, số cổng cần tránh nằm trong khoảng từ 0 đến 1023 (bao gồm) vì chúng là cổng hệ thống dành riêng.

public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; }}

Tạo ứng dụng mạng trong Java Step4
Tạo ứng dụng mạng trong Java Step4

Bước 4. Tạo máy chủ

Máy chủ được liên kết với địa chỉ và cổng và lắng nghe các kết nối đến. Trong Java,

ServerSocket

đại diện cho điểm cuối phía máy chủ và chức năng của nó đang chấp nhận các kết nối mới.

ServerSocket

không có luồng để đọc và gửi dữ liệu vì nó không đại diện cho kết nối giữa máy chủ và máy khách.

nhập java.net. InetAddress; nhập java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); }}

Tạo ứng dụng mạng trong Java Step5
Tạo ứng dụng mạng trong Java Step5

Bước 5. Đăng nhập khởi động máy chủ

Đối với mục đích ghi nhật ký, hãy in ra bảng điều khiển mà máy chủ đã được khởi động.

nhập java.net. InetAddress; nhập java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); }}

Tạo ứng dụng mạng trong Java Step6
Tạo ứng dụng mạng trong Java Step6

Bước 6. Tạo khách hàng

Máy khách được liên kết với địa chỉ và cổng của máy chủ và lắng nghe các gói (tin nhắn) sau khi kết nối được thiết lập. Trong Java,

Ổ cắm

đại diện cho điểm cuối phía máy khách được kết nối với máy chủ hoặc kết nối (từ máy chủ) đến máy khách và được sử dụng để giao tiếp với bên ở đầu bên kia.

nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); }}

Tạo ứng dụng mạng trong Java Step7
Tạo ứng dụng mạng trong Java Step7

Bước 7. Ghi nhật ký cố gắng kết nối

Đối với mục đích ghi nhật ký, hãy in ra bảng điều khiển mà kết nối đã được thử.

nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); }}

Tạo ứng dụng mạng trong Java Step8
Tạo ứng dụng mạng trong Java Step8

Bước 8. Thiết lập kết nối

Máy khách sẽ không bao giờ kết nối trừ khi máy chủ lắng nghe và chấp nhận, hay nói cách khác là thiết lập kết nối. Trong Java, các kết nối được thiết lập bằng cách sử dụng

Chấp nhận()

phương pháp của

ServerSocket

lớp. Phương thức sẽ chặn thực thi cho đến khi một máy khách kết nối.

nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); }}

Tạo ứng dụng mạng trong Java Step9
Tạo ứng dụng mạng trong Java Step9

Bước 9. Đăng nhập kết nối đã thiết lập

Đối với mục đích ghi nhật ký, hãy in ra bảng điều khiển mà kết nối giữa máy chủ và máy khách đã được thiết lập.

nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); }}

Tạo ứng dụng mạng trong Java Step10
Tạo ứng dụng mạng trong Java Step10

Bước 10. Chuẩn bị các luồng giao tiếp

Giao tiếp được thực hiện qua các luồng và, trong ứng dụng này, các luồng thô của (kết nối từ) máy chủ (đến máy khách) và máy khách cần được liên kết với các luồng dữ liệu hoặc đối tượng. Hãy nhớ rằng cả hai bên cần sử dụng cùng một loại luồng.

  • Các luồng dữ liệu

    nhập java.io. DataInputStream; nhập java.io. DataOutputStream; nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); DataOutputStream clientOut = new DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = new DataInputStream (client.getInputStream ()); DataOutputStream serverOut = new DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = new DataInputStream (connection.getInputStream ()); }}

  • Các luồng đối tượng

    Khi nhiều luồng đối tượng được sử dụng, các luồng đầu vào phải được khởi tạo theo thứ tự giống như các luồng đầu ra vì

    ObjectOutputStream

    gửi một tiêu đề cho bên kia và

    ObjectInputStream

    chặn thực thi cho đến khi nó đọc tiêu đề.

    nhập java.io. ObjectInputStream; nhập java.io. ObjectOutputStream; nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); ObjectOutputStream clientOut = new ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = new ObjectOutputStream (connect.getOutputStream ()); ObjectInputStream clientIn = new ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connection.getInputStream ()); }}

    Thứ tự như được chỉ định trong đoạn mã trên có thể dễ nhớ hơn - đầu tiên khởi tạo các luồng đầu ra sau đó khởi tạo các luồng đầu vào theo cùng một thứ tự. Tuy nhiên, một thứ tự khác để khởi tạo luồng đối tượng như sau:

    ObjectOutputStream clientOut = new ObjectOutputStream (client.getOutputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connect.getInputStream ()); ObjectOutputStream serverOut = new ObjectOutputStream (connect.getOutputStream ()); ObjectInputStream clientIn = new ObjectInputStream (client.getInputStream ());

Tạo ứng dụng mạng trong Java Step11
Tạo ứng dụng mạng trong Java Step11

Bước 11. Ghi lại rằng liên lạc đã sẵn sàng

Đối với mục đích ghi nhật ký, hãy in ra bảng điều khiển rằng giao tiếp đã sẵn sàng.

// mã bị bỏ qua import java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); // mã bị bỏ qua System.out.println ("Giao tiếp đã sẵn sàng."); }}

Tạo ứng dụng mạng trong Java Step12
Tạo ứng dụng mạng trong Java Step12

Bước 12. Soạn tin nhắn

Trong ứng dụng này,

Chào thế giới

văn bản sẽ được gửi đến máy chủ dưới dạng

byte

hoặc

Dây

. Khai báo một biến kiểu phụ thuộc vào luồng được sử dụng. Sử dụng

byte

cho các luồng dữ liệu và

Dây

cho các luồng đối tượng.

  • Các luồng dữ liệu

    Sử dụng các luồng dữ liệu, tuần tự hóa được thực hiện bằng cách chuyển đổi các đối tượng thành các kiểu dữ liệu nguyên thủy hoặc

    Dây

    . Trong trường hợp này,

    Dây

    được chuyển đổi thành

    byte

    thay vì viết bằng cách sử dụng

    writeBytes ()

    để hiển thị cách nó sẽ được thực hiện với các đối tượng khác, chẳng hạn như hình ảnh hoặc các tệp khác.

    nhập java.io. DataInputStream; nhập java.io. DataOutputStream; nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); DataOutputStream clientOut = new DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = new DataInputStream (client.getInputStream ()); DataOutputStream serverOut = new DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = new DataInputStream (connection.getInputStream ()); System.out.println ("Giao tiếp đã sẵn sàng."); byte messageOut = "Xin chào Thế giới".getBytes (); }}

  • Các luồng đối tượng

    nhập java.io. ObjectInputStream; nhập java.io. ObjectOutputStream; nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); ObjectOutputStream clientOut = new ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = new ObjectOutputStream (connect.getOutputStream ()); ObjectInputStream clientIn = new ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connect.getInputStream ()); System.out.println ("Giao tiếp đã sẵn sàng."); String messageOut = "Hello World"; }}

Tạo ứng dụng mạng trong Java Step13
Tạo ứng dụng mạng trong Java Step13

Bước 13. Gửi tin nhắn

Ghi dữ liệu vào luồng đầu ra và xóa luồng để đảm bảo dữ liệu đã được ghi toàn bộ.

  • Các luồng dữ liệu

    Độ dài của một tin nhắn cần được gửi trước để bên kia biết nó cần đọc bao nhiêu byte. Sau khi độ dài được gửi dưới dạng một kiểu số nguyên nguyên thủy, các byte có thể được gửi.

    nhập java.io. DataInputStream; nhập java.io. DataOutputStream; nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); DataOutputStream clientOut = new DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = new DataInputStream (client.getInputStream ()); DataOutputStream serverOut = new DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = new DataInputStream (connection.getInputStream ()); System.out.println ("Giao tiếp đã sẵn sàng."); byte messageOut = "Xin chào Thế giới".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); }}

  • Các luồng đối tượng

    nhập java.io. ObjectInputStream; nhập java.io. ObjectOutputStream; nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); ObjectOutputStream clientOut = new ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = new ObjectOutputStream (connect.getOutputStream ()); ObjectInputStream clientIn = new ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connect.getInputStream ()); System.out.println ("Giao tiếp đã sẵn sàng."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); }}

Tạo ứng dụng mạng trong Java Step14
Tạo ứng dụng mạng trong Java Step14

Bước 14. Ghi nhật ký tin nhắn đã gửi

Đối với mục đích ghi nhật ký, hãy in ra bảng điều khiển mà tin nhắn đã được gửi đi.

  • Các luồng dữ liệu

    nhập java.io. DataInputStream; nhập java.io. DataOutputStream; nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); DataOutputStream clientOut = new DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = new DataInputStream (client.getInputStream ()); DataOutputStream serverOut = new DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = new DataInputStream (connection.getInputStream ()); System.out.println ("Giao tiếp đã sẵn sàng."); byte messageOut = "Xin chào Thế giới".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Tin nhắn được gửi đến máy chủ:" + new String (messageOut)); }}

  • Các luồng đối tượng

    nhập java.io. ObjectInputStream; nhập java.io. ObjectOutputStream; nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); ObjectOutputStream clientOut = new ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = new ObjectOutputStream (connect.getOutputStream ()); ObjectInputStream clientIn = new ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connect.getInputStream ()); System.out.println ("Giao tiếp đã sẵn sàng."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Tin nhắn được gửi đến máy chủ:" + messageOut); }}

Tạo ứng dụng mạng trong Java Step15
Tạo ứng dụng mạng trong Java Step15

Bước 15. Đọc tin nhắn

Đọc dữ liệu từ luồng đầu vào và chuyển đổi nó. Vì chúng tôi biết chính xác loại dữ liệu đã gửi, chúng tôi sẽ tạo

Dây

từ

byte

hoặc đúc

Sự vật

đến

Dây

mà không cần kiểm tra, tùy thuộc vào luồng được sử dụng.

  • Các luồng dữ liệu

    Vì độ dài được gửi đầu tiên và byte sau đó, việc đọc phải được thực hiện theo cùng một thứ tự. Trong trường hợp độ dài bằng 0, không có gì để đọc. Đối tượng được deserialized khi các byte được chuyển đổi trở lại thành một thể hiện, trong trường hợp này là của

    Dây

    nhập java.io. DataInputStream; nhập java.io. DataOutputStream; nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); DataOutputStream clientOut = new DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = new DataInputStream (client.getInputStream ()); DataOutputStream serverOut = new DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = new DataInputStream (connection.getInputStream ()); System.out.println ("Giao tiếp đã sẵn sàng."); byte messageOut = "Xin chào Thế giới".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Tin nhắn được gửi đến máy chủ:" + new String (messageOut)); int length = serverIn.readInt (); if (length> 0) {byte messageIn = new byte [length]; serverIn.readFully (messageIn, 0, messageIn.length); }}}

  • Các luồng đối tượng

    nhập java.io. ObjectInputStream; nhập java.io. ObjectOutputStream; nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); ObjectOutputStream clientOut = new ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = new ObjectOutputStream (connect.getOutputStream ()); ObjectInputStream clientIn = new ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connect.getInputStream ()); System.out.println ("Giao tiếp đã sẵn sàng."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Tin nhắn được gửi đến máy chủ:" + messageOut); String messageIn = (String) serverIn.readObject (); }}

Tạo ứng dụng mạng trong Java Step16
Tạo ứng dụng mạng trong Java Step16

Bước 16. Ghi nhật ký đã đọc tin nhắn

Đối với mục đích ghi nhật ký, hãy in ra bảng điều khiển mà tin nhắn đã nhận được và in nội dung của nó.

  • Các luồng dữ liệu

    nhập java.io. DataInputStream; nhập java.io. DataOutputStream; nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); DataOutputStream clientOut = new DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = new DataInputStream (client.getInputStream ()); DataOutputStream serverOut = new DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = new DataInputStream (connection.getInputStream ()); System.out.println ("Giao tiếp đã sẵn sàng."); byte messageOut = "Xin chào Thế giới".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Tin nhắn được gửi đến máy chủ:" + new String (messageOut)); int length = serverIn.readInt (); if (length> 0) {byte messageIn = new byte [length]; serverIn.readFully (messageIn, 0, messageIn.length); System.out.println ("Tin nhắn nhận được từ máy khách:" + new String (messageIn)); }}}

  • Các luồng đối tượng

    nhập java.io. ObjectInputStream; nhập java.io. ObjectOutputStream; nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); ObjectOutputStream clientOut = new ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = new ObjectOutputStream (connect.getOutputStream ()); ObjectInputStream clientIn = new ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = new ObjectInputStream (connect.getInputStream ()); System.out.println ("Giao tiếp đã sẵn sàng."); String messageOut = "Hello World"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Tin nhắn được gửi đến máy chủ:" + messageOut); String messageIn = (String) serverIn.readObject (); System.out.println ("Tin nhắn nhận được từ máy khách:" + messageIn); }}

Tạo ứng dụng mạng trong Java Step17
Tạo ứng dụng mạng trong Java Step17

Bước 17. Ngắt kết nối các kết nối

Kết nối bị ngắt khi một bên đóng luồng của mình. Trong Java, bằng cách đóng luồng đầu ra, ổ cắm liên quan và luồng đầu vào cũng bị đóng. Khi một bên ở đầu bên kia phát hiện ra kết nối đã chết, bên đó cũng cần phải đóng luồng đầu ra của mình để tránh rò rỉ bộ nhớ.

// mã bị bỏ qua import java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); // mã bị bỏ qua System.out.println ("Giao tiếp đã sẵn sàng."); // mã bị bỏ qua clientOut.close (); serverOut.close (); }}

Tạo ứng dụng mạng trong Java Step18 V2
Tạo ứng dụng mạng trong Java Step18 V2

Bước 18. Ngắt kết nối nhật ký

Đối với mục đích ghi nhật ký, kết nối in với bảng điều khiển đã bị ngắt kết nối.

// mã bị bỏ qua import java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); // mã bị bỏ qua System.out.println ("Giao tiếp đã sẵn sàng."); // mã bị bỏ qua clientOut.close (); serverOut.close (); System.out.println ("Kết nối đã đóng."); }}

Tạo ứng dụng mạng trong Java Step19
Tạo ứng dụng mạng trong Java Step19

Bước 19. Chấm dứt máy chủ

Các kết nối bị ngắt kết nối, nhưng máy chủ vẫn hoạt động. Như

ServerSocket

không được liên kết với bất kỳ luồng nào, luồng đó cần được đóng một cách rõ ràng bằng cách gọi

gần()

phương pháp.

// mã bị bỏ qua import java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); // mã bị bỏ qua System.out.println ("Giao tiếp đã sẵn sàng."); // mã bị bỏ qua clientOut.close (); serverOut.close (); System.out.println ("Kết nối đã đóng."); server.close (); }}

Tạo ứng dụng mạng trong Java Step20
Tạo ứng dụng mạng trong Java Step20

Bước 20. Ghi nhật ký kết thúc máy chủ

Đối với mục đích ghi nhật ký, quá trình in tới máy chủ bảng điều khiển đã bị chấm dứt.

// mã bị bỏ qua import java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. Socket; public class NetworkAppExample {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; ServerSocket server = new ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Máy chủ đã khởi động."); Socket client = new Socket (máy chủ, cổng); System.out.println ("Đang kết nối với máy chủ…"); Kết nối ổ cắm = server.accept (); System.out.println ("Kết nối được thiết lập."); // mã bị bỏ qua System.out.println ("Giao tiếp đã sẵn sàng."); // mã bị bỏ qua clientOut.close (); serverOut.close (); System.out.println ("Kết nối đã đóng."); server.close (); System.out.println ("Máy chủ đã kết thúc."); }}

Tạo ứng dụng mạng trong Java Step21
Tạo ứng dụng mạng trong Java Step21

Bước 21. Biên dịch và chạy

Việc ghi nhật ký cho phép chúng tôi biết liệu ứng dụng có thành công hay không. Sản lượng mong đợi:

Máy chủ đã khởi động. Đang kết nối với máy chủ… Kết nối được thiết lập. Thông tin liên lạc đã sẵn sàng. Tin nhắn được gửi đến máy chủ: Hello World Tin nhắn nhận được từ máy khách: Hello World Connections đã đóng. Máy chủ đã kết thúc.

Trong trường hợp đầu ra của bạn không giống như ở trên, điều này khó có thể xảy ra, có một số giải pháp:

  • Nếu đầu ra dừng ở dòng

    Kết nối thành lập.

    và các luồng đối tượng được sử dụng, xả từng

    ObjectOutputStream

  • ngay sau khi khởi tạo vì các tiêu đề, vì lý do nào đó, không được gửi.
  • Nếu đầu ra in

    java.net. BindException: Địa chỉ đã được sử dụng

  • hãy chọn một số cổng khác vì một số được chỉ định đã được sử dụng.

Lời khuyên

  • Kết nối với máy chủ trên một mạng khác được thực hiện bằng cách kết nối với địa chỉ IP bên ngoài của thiết bị chạy máy chủ có cổng chuyển tiếp.
  • Kết nối với máy chủ trên cùng một mạng được thực hiện bằng cách kết nối với địa chỉ IP riêng của thiết bị chạy máy chủ hoặc chuyển tiếp một cổng và kết nối với địa chỉ IP bên ngoài của thiết bị.
  • Có những phần mềm, chẳng hạn như Hamachi, cho phép kết nối với máy chủ trên một mạng khác mà không cần chuyển tiếp cổng, nhưng nó yêu cầu cài đặt phần mềm trên cả hai thiết bị.

Các ví dụ

Các ứng dụng mạng sử dụng đầu vào / đầu ra chặn cần sử dụng luồng. Các ví dụ sau đây cho thấy việc triển khai máy chủ và máy khách tối giản với các luồng. Mã mạng về cơ bản giống như trong bài viết ngoại trừ một số đoạn mã đã được đồng bộ hóa, chuyển vào các luồng và các ngoại lệ được xử lý.

Server.java

nhập java.io. IOException; nhập java.net. InetAddress; nhập java.net. ServerSocket; nhập java.net. SocketException; nhập java.net. UnknownHostException; nhập java.util. ArrayList; nhập java.util. Collections; nhập java.util. List; / ** * Lớp {@code Server} đại diện cho điểm cuối của máy chủ trong mạng. {@code Server} sau khi được liên kết với một địa chỉ IP * và cổng nhất định, sẽ thiết lập kết nối với ứng dụng khách và có thể giao tiếp với họ hoặc ngắt kết nối với họ. *

* Lớp này là luồng an toàn. * * @version 1.0 * @see Client * @see Connection * / public class Máy chủ triển khai máy chủ ServerSocket riêng Runnable {; danh sách riêng tư kết nối; Chủ đề riêng tư; private cuối cùng đối tượng kết nốiLock = new Object (); / ** * Xây dựng {@code Server} tương tác với các máy khách trên tên máy chủ và cổng được chỉ định với độ dài tối đa được yêu cầu * được chỉ định của hàng đợi các máy khách đến. * * @param host Địa chỉ máy chủ để sử dụng. * Cổng @param Số cổng sử dụng. * @param backlog Độ dài tối đa được yêu cầu của hàng đợi khách hàng đến. * @throws NetworkException Nếu lỗi xảy ra khi khởi động máy chủ. * / public Server (String host, int port, int backlog) ném NetworkException {try {server = new ServerSocket (port, backlog, InetAddress.getByName (host)); } catch (UnknownHostException e) {throw new NetworkException ("Không thể phân giải tên máy chủ:" + máy chủ, e); } catch (IllegalArgumentException e) {throw new NetworkException ("Số cổng phải từ 0 đến 65535 (bao gồm):" + cổng); } catch (IOException e) {throw new NetworkException ("Không thể khởi động máy chủ.", e); } kết nối = Collections.synchronizedList (new ArrayList ()); thread = new Thread (this); thread.start (); } / ** * Tạo {@code Server} tương tác với các máy khách trên tên máy chủ và cổng được chỉ định. * * @param host Địa chỉ máy chủ để liên kết. * Cổng @param Số cổng để liên kết. * @throws NetworkException Nếu lỗi xảy ra khi khởi động máy chủ. * / public Server (Máy chủ chuỗi, cổng int) ném NetworkException {this (máy chủ, cổng, 50); } / ** * Nghe, chấp nhận và đăng ký các kết nối đến từ máy khách. * / @Override public void run () {while (! Server.isClosed ()) {try {links.add (new Connection (server.accept ())); } catch (SocketException e) {if (! e.getMessage (). equals ("Socket đã đóng")) {e.printStackTrace (); }} catch (NetworkException | IOException e) {e.printStackTrace (); }}} / ** * Gửi dữ liệu đến tất cả các khách hàng đã đăng ký. * * Dữ liệu @param Dữ liệu cần gửi. * @throws IllegalStateException Nếu cố gắng ghi dữ liệu khi máy chủ ngoại tuyến. * @throws IllegalArgumentException Nếu dữ liệu để gửi là rỗng. * / public void broadcast (Object data) {if (server.isClosed ()) {throw new IllegalStateException ("Dữ liệu chưa được gửi, máy chủ đang ngoại tuyến."); } if (data == null) {ném mới IllegalArgumentException ("dữ liệu null"); } sync (linksLock) {for (Kết nối kết nối: các kết nối) {try {connect.send (data); System.out.println ("Dữ liệu được gửi đến máy khách thành công."); } catch (NetworkException e) {e.printStackTrace (); }}}} / ** * Gửi thông báo ngắt kết nối và ngắt kết nối ứng dụng đã chỉ định. * * @param kết nối Máy khách để ngắt kết nối. * @throws NetworkException Nếu xảy ra lỗi khi đóng kết nối. * / public void ngắt kết nối (Kết nối kết nối) ném NetworkException {if (results.remove (kết nối)) {connect.close (); }} / ** * Gửi thông báo ngắt kết nối tới tất cả các máy khách, ngắt kết nối chúng và kết thúc máy chủ. * / public void close () ném NetworkException {sync (linksLock) {for (Kết nối kết nối: các kết nối) {try {connect.close (); } catch (NetworkException e) {e.printStackTrace (); }}} kết nối.clear (); thử {server.close (); } catch (IOException e) {throw new NetworkException ("Lỗi khi đóng máy chủ."); } cuối cùng là {thread.interrupt (); }} / ** * Trả về máy chủ có trực tuyến hay không. * * @return Đúng nếu máy chủ trực tuyến. Sai, ngược lại. * / public boolean isOnline () {return! server.isClosed (); } / ** * Trả về một mảng các máy khách đã đăng ký. * / public Connection getConnections () {sync (linksLock) {return results.toArray (new Connection [links.size ()]); }}}

Client.java

nhập java.io. IOException; nhập java.net. Socket; nhập java.net. UnknownHostException; / ** * Lớp {@code Client} đại diện cho một điểm cuối của máy khách trong mạng. {@code Client}, sau khi được kết nối với một máy chủ * nhất định, được đảm bảo chỉ có thể giao tiếp với máy chủ. Các máy khách khác có nhận được dữ liệu * hay không phụ thuộc vào việc triển khai máy chủ. *

* Lớp này là luồng an toàn. * * @version 1.0 * @see Server * @see Connection * / public class Client {kết nối private Connection; / ** * Tạo {@code Client} được kết nối với máy chủ trên máy chủ và cổng được chỉ định. * * @param host Địa chỉ máy chủ để liên kết. * Cổng @param Số cổng để liên kết. * @throws NetworkException Nếu lỗi xảy ra khi khởi động máy chủ. * / public Client (Máy chủ chuỗi, cổng int) ném NetworkException {try {connection = new Connection (new Socket (máy chủ, cổng)); } catch (UnknownHostException e) {throw new NetworkException ("Không thể phân giải tên máy chủ:" + máy chủ, e); } catch (IllegalArgumentException e) {ném NetworkException mới ("Số cổng phải từ 0 đến 65535 (bao gồm):" + cổng); } catch (IOException e) {throw new NetworkException ("Không thể khởi động máy chủ.", e); }} / ** * Gửi dữ liệu cho bên kia. * * Dữ liệu @param Dữ liệu cần gửi. * @throws NetworkException Nếu việc ghi vào luồng đầu ra không thành công. * @throws IllegalStateException Nếu cố gắng ghi dữ liệu khi kết nối bị đóng. * @throws IllegalArgumentException Nếu dữ liệu để gửi là rỗng. * @throws UnsupportedOperationException Nếu cố gắng gửi loại dữ liệu không được hỗ trợ. * / public void send (Object data) ném NetworkException {connect.send (data); } / ** * Gửi thông báo ngắt kết nối tới và đóng kết nối với máy chủ. * / public void close () ném NetworkException {connect.close (); } / ** * Trả về máy khách có được kết nối với máy chủ hay không. * * @return Đúng nếu máy khách được kết nối. Sai, ngược lại. * / public boolean isOnline () {return connect.isConnected (); } / ** * Trả về phiên bản {@link Connection} của ứng dụng khách. * / public Connection getConnection () {return connection; }}

Connection.java

nhập java.io. DataInputStream; nhập java.io. DataOutputStream; nhập java.io. IOException; nhập java.net. Socket; nhập java.net. SocketException; / ** * Lớp {@code Connection} đại diện cho kết nối từ máy chủ đến máy khách hoặc điểm cuối của máy khách trong mạng * {@code Connection}, sau khi được kết nối, có thể trao đổi dữ liệu với bên hoặc các bên khác, tùy thuộc trên máy chủ * triển khai. *

* Lớp này là luồng an toàn. * * @version 1.0 * @see Server * @see Client * / public class Connection triển khai Runnable {private Socket socket; DataOutputStream riêng tư ra ngoài; DataInputStream riêng tư trong; Chủ đề riêng tư; private final Object writeLock = new Object (); private final Object readLock = new Object (); / ** * Tạo {@code Connection} bằng cách sử dụng các luồng của một {@link Socket} được chỉ định. * * @param socket Socket để tìm nạp các luồng từ đó.* / public Connection (Socket socket) ném NetworkException {if (socket == null) {ném new IllegalArgumentException ("null socket"); } this.socket = socket; thử {out = new DataOutputStream (socket.getOutputStream ()); } catch (IOException e) {throw new NetworkException ("Không thể truy cập luồng đầu ra.", e); } thử {in = new DataInputStream (socket.getInputStream ()); } catch (IOException e) {throw new NetworkException ("Không thể truy cập luồng đầu vào.", e); } thread = new Thread (this); thread.start (); } / ** * Đọc tin nhắn khi kết nối với bên kia vẫn còn. * / @Override public void run () {while (! Socket.isClosed ()) {try {int IDfier; byte byte; đồng bộ hóa (readLock) {định danh = in.readInt (); int length = in.readInt (); if (length> 0) {byte = new byte [length]; in.readFully (byte, 0, byte.length); } else {tiếp tục; }} switch (mã định danh) {trường hợp Mã định danh. INTERNAL: Lệnh chuỗi = new String (byte); if (command.equals ("ngắt kết nối")) {if (! socket.isClosed ()) {System.out.println ("Đã nhận được gói ngắt kết nối."); thử {close (); } catch (NetworkException e) {return; } } } nghỉ; case Mã định danh. TEXT: System.out.println ("Thông báo nhận được:" + new String (byte)); nghỉ; default: System.out.println ("Đã nhận dữ liệu không được công nhận."); }} catch (SocketException e) {if (! e.getMessage (). equals ("Socket đã đóng")) {e.printStackTrace (); }} catch (IOException e) {e.printStackTrace (); }}} / ** * Gửi dữ liệu cho bên kia. * * Dữ liệu @param Dữ liệu cần gửi. * @throws NetworkException Nếu việc ghi vào luồng đầu ra không thành công. * @throws IllegalStateException Nếu cố gắng ghi dữ liệu khi kết nối bị đóng. * @throws IllegalArgumentException Nếu dữ liệu để gửi là rỗng. * @throws UnsupportedOperationException Nếu cố gắng gửi loại dữ liệu không được hỗ trợ. * / public void send (Object data) throws NetworkException {if (socket.isClosed ()) {throw new IllegalStateException ("Dữ liệu không được gửi, kết nối bị đóng."); } if (data == null) {ném mới IllegalArgumentException ("dữ liệu null"); } định danh int; byte byte; if (data instanceof String) {IDfier = Mã định danh. TEXT; byte = ((Chuỗi) dữ liệu).getBytes (); } else {ném mới UnsupportedOperationException ("Kiểu dữ liệu không được hỗ trợ:" + data.getClass ()); } thử {sync (writeLock) {out.writeInt (mã định danh); out.writeInt (byte.length); out.write (byte); out.flush (); }} catch (IOException e) {throw new NetworkException ("Không thể gửi dữ liệu.", e); }} / ** * Gửi thông báo ngắt kết nối tới và đóng kết nối với bên kia. * / public void close () ném NetworkException {if (socket.isClosed ()) {throw new IllegalStateException ("Kết nối đã bị đóng."); } thử {byte message = "ngắt kết nối".getBytes (); đồng bộ hóa (writeLock) {out.writeInt (Mã định danh. INTERNAL); out.writeInt (message.length); out.write (tin nhắn); out.flush (); }} catch (IOException e) {System.out.println ("Không thể gửi thông báo ngắt kết nối."); } thử {sync (writeLock) {out.close (); }} catch (IOException e) {throw new NetworkException ("Lỗi khi đóng kết nối.", e); } cuối cùng là {thread.interrupt (); }} / ** * Trả về kết nối với bên kia có còn hoạt động hay không. * * @return Đúng nếu kết nối vẫn còn. Sai, ngược lại. * / public boolean isConnected () {return! socket.isClosed (); }}

Mã định danh.java

/ ** * Lớp {@code Recogfier} chứa các hằng số được {@link Connection} sử dụng để tuần tự hóa và giải mã hóa dữ liệu * được gửi qua mạng. * * @version 1.0 * @see Kết nối * / Công khai mã định danh lớp cuối cùng {/ ** * Mã định danh cho tin nhắn nội bộ. * / public static final int INTERNAL = 1; / ** * Định danh cho tin nhắn văn bản. * / public static final int TEXT = 2; }

NetworkException.java

/ ** * Lớp {@code NetworkException} chỉ ra một lỗi liên quan đến mạng. * / public class NetworkException mở rộng Exception {/ ** * Tạo {@code NetworkException} với {@code null} làm thông điệp của nó. * / public NetworkException () {} / ** * Tạo {@code NetworkException} với thông báo được chỉ định. * * Thông báo @param Một thông báo để mô tả lỗi. * / public NetworkException (String message) {super (message); } / ** * Tạo {@code NetworkException} với thông báo và nguyên nhân được chỉ định. * * Thông báo @param Một thông báo để mô tả lỗi. * @param nguyên nhân Một nguyên nhân gây ra lỗi. * / public NetworkException (Chuỗi thông báo, Nguyên nhân có thể ném) {super (thông báo, nguyên nhân); } / ** * Tạo {@code NetworkException} với nguyên nhân được chỉ định. * * @param nguyên nhân Một nguyên nhân gây ra lỗi. * / public NetworkException (Nguyên nhân có thể ném) {super (nguyên nhân); }}

UseExample.java

/ ** * Lớp {@code UsageExample} hiển thị việc sử dụng {@link Server} và {@link Client}. Ví dụ này sử dụng * {@link Thread # sleep (long)} để đảm bảo mọi phân đoạn đều được thực thi vì việc bắt đầu và đóng nhanh khiến một số phân đoạn * không thực thi. * * @version 1.0 * @see Server * @see Client * / public class Cách sử dụng Ví dụ {public static void main (String args) ném Exception {String host = "localhost"; cổng int = 10430; Máy chủ server = Máy chủ mới (máy chủ, cổng); Máy khách máy khách = Máy khách mới (máy chủ, cổng); Thread.sleep (100L); client.send ("Xin chào."); server.broadcast ("Này, anh bạn!"); Thread.sleep (100L); server.disconnect (server.getConnections () [0]); // hoặc client.close () để ngắt kết nối khỏi server.close phía máy khách (); }}

Đề xuất: