您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關Java中如何進行TCP和套接字入門,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
JDK 提供了對 TCP(Transmission Control Protocol,傳輸控制協議)和 UDP(User Datagram Protocol,用戶數據報協議)這兩個數據傳輸協議的支持。本文開始探討 TCP。
TCP 基礎知識
在“服務器-客戶端”這種架構中,服務器和客戶端各自維護一個端點,兩個端點需要通過網絡進行數據交換。TCP 為這種需求提供了一種可靠的流式連接,流式的意思是傳出和收到的數據都是連續的字節,沒有對數據量進行大小限制。一個端點由 IP 地址和端口構成(專業術語為“元組 {IP 地址, 端口}”)。這樣,一個連接就可以由元組 {本地地址, 本地端口, 遠程地址, 遠程端口} 來表示。
連接過程
在 TCP 編程接口中,端點體現為 TCP 套接字。共有兩種 TCP 套接字:主動和被動,“被動”狀態也常被稱為“偵聽”狀態。服務器和客戶端利用套接字進行連接的過程如下:
1、服務器創建一個被動套接字,開始循環偵聽客戶端的連接。
2、客戶端創建一個主動套接字,連接服務器。
3、服務器接受客戶端的連接,并創建一個代表該連接的主動套接字。
4、服務器和客戶端通過步驟 2 和 3 中創建的兩個主動套接字進行數據傳輸。
下面是連接過程的圖解:
一個簡單的 TCP 服務器
JDK 提供了 ServerSocket 類來代表 TCP 服務器的被動套接字。下面的代碼演示了一個簡單的 TCP 服務器(多線程阻塞模式),它不斷偵聽并接受客戶端的連接,然后將客戶端發送過來的文本按行讀取,全文轉換為大寫后返回給客戶端,直到客戶端發送文本行 bye:
public class TcpServer implements Runnable { private ServerSocket serverSocket; public TcpServer(int port) throws IOException { // 創建綁定到某個端口的 TCP 服務器被動套接字。 serverSocket = new ServerSocket(port); } @Override public void run() { while (true) { try { // 以阻塞的方式接受一個客戶端連接,返回代表該連接的主動套接字。 Socket socket = serverSocket.accept(); // 在新線程中處理客戶端連接。 new Thread(new ClientHandler(socket)).start(); } catch (IOException ex) { ex.printStackTrace(); } } } } public class ClientHandler implements Runnable { private Socket socket; public ClientHandler(Socket socket) { this.socket = Objects.requireNonNull(socket); } @Override public void run() { try (Socket s = socket) { // 減少代碼量的花招…… // 包裝套接字的輸入流以讀取客戶端發送的文本行。 BufferedReader in = new BufferedReader(new InputStreamReader( s.getInputStream(), StandardCharsets.UTF_8)); // 包裝套接字的輸出流以向客戶端發送轉換結果。 PrintWriter out = new PrintWriter(new OutputStreamWriter( s.getOutputStream(), StandardCharsets.UTF_8), true); String line = null; while ((line = in.readLine()) != null) { if (line.equals("bye")) { break; } // 將轉換結果輸出給客戶端。 out.println(line.toUpperCase(Locale.ENGLISH)); } } catch (IOException ex) { ex.printStackTrace(); } } }
阻塞模式的編程方式簡單,但存在性能問題,因為服務器線程會卡死在接受客戶端的 accept() 方法上,不能有效利用資源。套接字支持非阻塞模式,現在暫時略過。
一個簡單的 TCP 客戶端
JDK 提供了 Socket 類來代表 TCP 客戶端的主動套接字。下面的代碼演示了上述服務器的客戶端:
public class TcpClient implements Runnable { private Socket socket; public TcpClient(String host, int port) throws IOException { // 創建連接到服務器的套接字。 socket = new Socket(host, port); } @Override public void run() { try (Socket s = socket) { // 再次減少代碼量…… // 包裝套接字的輸出流以向服務器發送文本行。 PrintWriter out = new PrintWriter(new OutputStreamWriter( s.getOutputStream(), StandardCharsets.UTF_8), true); // 包裝套接字的輸入流以讀取服務器返回的文本行。 BufferedReader in = new BufferedReader(new InputStreamReader( s.getInputStream(), StandardCharsets.UTF_8)); Console console = System.console(); String line = null; while ((line = console.readLine()) != null) { if (line.equals("bye")) { break; } // 將文本行發送給服務器。 out.println(line); // 打印服務器返回的文本行。 console.writer().println(in.readLine()); } // 通知服務器關閉連接。 out.println("bye"); } catch (IOException ex) { ex.printStackTrace(); } } }
從 JDK 文檔可以看到,ServerSocket 和 Socket 在初始化的時候,可以設定一些參數,還支持延遲綁定。這些東西對性能和行為都有所影響。后續兩篇文章將分別詳解這兩個類的初始化。
看完上述內容,你們對Java中如何進行TCP和套接字入門有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。