Java【網絡原理】(3)網絡編程續


目錄

1.前言

2.正文

2.1ServerSocket類

2.2Socket類

2.3Tcp回顯服務器

2.3.1TcpEchoServer

2.3.2TcpEchoClient

3.小結


1.前言

哈嘍大家好,今天繼續進行計算機網絡的初階學習,今天學習的是tcp回顯服務器的實現,正文開始

2.正文

在正式講解Tcp回顯服務器,還要介紹兩個包,一個是ServerSocket包,這個包是專門給服務器用的,Socket包是服務器和客戶端都會用,下文詳解。

2.1ServerSocket類

Java中的ServerSocket類是用于在服務器端監聽客戶端連接請求的核心類,屬于java.net包。它允許服務器應用程序在指定端口上等待客戶端的連接,并為每個連接創建一個Socket對象進行通信。


核心作用

  • 監聽端口:綁定到特定端口,等待客戶端連接。

  • 接受連接:通過accept()方法阻塞等待客戶端連接,返回代表客戶端的Socket對象。

  • 管理連接隊列:通過backlog參數設置等待連接隊列的最大長度。

關鍵方法

  1. 構造方法

    • ServerSocket(int port):綁定到指定端口。

    • ServerSocket(int port, int backlog):指定端口和連接隊列長度。

    • ServerSocket(int port, int backlog, InetAddress bindAddr):綁定到特定IP地址的端口。

  2. 核心方法

    • Socket accept():阻塞等待客戶端連接,返回連接的Socket對象。

    • void bind(SocketAddress endpoint):綁定到指定地址和端口。

    • void close():關閉服務器套接字。

    • int getLocalPort():獲取監聽的端口號。

    • void setSoTimeout(int timeout):設置accept()的超時時間(毫秒)。

使用流程

  1. 創建ServerSocket并綁定端口。

  2. 循環調用accept()接受客戶端連接。

  3. 為每個連接的Socket啟動新線程處理請求。

  4. 處理完成后關閉資源。

2.2Socket類

Java中的Socket類是用于實現網絡通信的核心類,屬于java.net包。它代表客戶端與服務器之間的一個連接,允許通過輸入流和輸出流進行雙向數據傳輸。Socket類通常與ServerSocket類配合使用,實現客戶端-服務器模型的通信。


核心作用

  • 建立連接:連接到服務器端的指定IP地址和端口。

  • 數據傳輸:通過輸入流(InputStream)和輸出流(OutputStream)進行數據交換。

  • 關閉連接:釋放資源并終止通信。

關鍵方法

  1. 構造方法

    • Socket(String host, int port):連接到指定主機和端口。

    • Socket(InetAddress address, int port):使用InetAddress對象連接到指定主機和端口。

    • Socket(String host, int port, InetAddress localAddr, int localPort):綁定到本地地址和端口,同時連接到遠程主機。

  2. 核心方法

    • InputStream getInputStream():獲取輸入流,用于讀取服務器發送的數據。

    • OutputStream getOutputStream():獲取輸出流,用于向服務器發送數據。

    • void close():關閉套接字,釋放資源。

    • void shutdownInput():關閉輸入流。

    • void shutdownOutput():關閉輸出流。

    • boolean isConnected():檢查是否已連接。

    • boolean isClosed():檢查是否已關閉。

使用流程

  1. 創建Socket對象并連接到服務器。

  2. 獲取輸入流和輸出流進行數據交換。

  3. 處理數據并完成通信。

  4. 關閉Socket和相關資源。

2.3Tcp回顯服務器

2.3.1TcpEchoServer

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** TCP回顯服務器實現類* 功能:接收客戶端消息并原樣返回(回顯)*/
public class TcpEchoServer {private ServerSocket serverSocket = null;  // 服務器套接字對象// 構造方法:初始化服務器并綁定端口public TcpEchoServer(int port) throws IOException {serverSocket = new ServerSocket(port);  // 創建ServerSocket并綁定指定端口}/*** 啟動服務器核心邏輯*/public void start() throws IOException {System.out.println("啟動服務器");// 創建線程池(動態調整線程數量,適合短任務)ExecutorService executorService = Executors.newCachedThreadPool();// 持續監聽客戶端連接while (true) {// 阻塞等待客戶端連接Socket clientSocket = serverSocket.accept();// 將客戶端連接提交給線程池處理executorService.submit(() -> {try {processConnection(clientSocket);  // 處理單個客戶端連接} catch (IOException e) {e.printStackTrace();}});}}/*** 處理單個客戶端連接的完整生命周期* @param clientSocket 客戶端套接字對象*/private void processConnection(Socket clientSocket) throws IOException {// 打印客戶端連接信息System.out.printf("[%s:%d] 客戶端上線!\n", clientSocket.getInetAddress(), clientSocket.getPort());// 使用try-with-resources自動關閉流try (InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {// 使用Scanner和PrintWriter包裝流對象Scanner scanner = new Scanner(inputStream);    // 輸入流掃描器PrintWriter printWriter = new PrintWriter(outputStream);  // 輸出流寫入器// 持續處理客戶端請求while (true) {// 1. 檢測連接狀態(若輸入流中沒有數據,說明客戶端斷開)if (!scanner.hasNext()) {System.out.printf("[%s:%d] 客戶端下線!\n", clientSocket.getInetAddress(), clientSocket.getPort());break;}// 2. 讀取請求并處理String request = scanner.next();    // 讀取客戶端請求(空格分隔)String response = process(request); // 處理請求生成響應// 3. 返回響應給客戶端printWriter.println(response);  // 寫入響應printWriter.flush();            // 強制刷新緩沖區}} catch (IOException e) {throw new RuntimeException(e);} finally {try {clientSocket.close();  // 確保關閉客戶端套接字} catch (IOException e) {throw new RuntimeException(e);}}}/*** 處理請求的核心邏輯(示例為簡單回顯)* @param request 客戶端請求內容* @return 返回與請求相同的字符串*/private String process(String request) {// 此處可添加業務邏輯(示例直接返回原內容)return request;}/*** 主方法:啟動服務器實例*/public static void main(String[] args) throws IOException {TcpEchoServer tcpEchoServer = new TcpEchoServer(9090);  // 創建服務器實例(端口9090)tcpEchoServer.start();  // 啟動服務器}
}

核心思路講解:


整體架構設計:

該代碼實現了一個多線程TCP回顯服務器,核心功能是接收客戶端發送的文本消息,并將消息原樣返回(回顯)。其架構設計遵循經典客戶端-服務器模型,核心特點包括:

  • 多線程處理:通過線程池動態分配線程,避免單線程阻塞導致的性能瓶頸。

  • 資源自動管理:利用try-with-resources確保流和套接字的自動釋放。

  • 松耦合設計:將連接處理(processConnection)與業務邏輯(process)分離,便于擴展。


核心組件解析:

(1) ServerSocket 的職責

  • 端口監聽:綁定到指定端口(如9090),通過accept()阻塞等待客戶端連接。

  • 連接隊列管理:默認使用操作系統提供的連接隊列(通過backlog參數可調整隊列長度)。

  • 生命周期控制:服務器運行時持續監聽,直到進程終止(代碼中未實現優雅關閉邏輯)。

(2) Socket 連接處理

  • 雙向通信:每個客戶端連接對應一個Socket對象,通過其輸入流(InputStream)和輸出流(OutputStream)實現數據交換。

  • 連接狀態檢測:通過scanner.hasNext()判斷客戶端是否斷開(輸入流關閉時返回false)。

(3) 線程池的作用

  • 動態資源分配Executors.newCachedThreadPool()創建的線程池會根據任務量自動擴展/收縮:

    • 空閑線程默認存活60秒后被回收。

    • 適合短生命周期任務(如HTTP請求)。

  • 避免線程爆炸:相比為每個連接直接創建new Thread(),線程池能有效控制系統資源占用。


3. 關鍵流程詳解:

(1) 啟動階段

  1. 初始化ServerSocket并綁定端口。

  2. 創建線程池,進入無限循環等待連接。

(2) 連接處理階段

  1. 接受連接accept()返回客戶端Socket對象。

  2. 提交任務:將processConnection方法包裝為任務提交到線程池。

  3. 處理請求

    • 通過Scanner逐詞讀取客戶端請求(空格分隔)。

    • 調用process()生成響應(此處簡單回顯)。

    • 通過PrintWriter寫回響應并強制刷新緩沖區。

(3) 連接終止

  1. 客戶端主動斷開scanner.hasNext()檢測到輸入流結束,跳出循環關閉連接。

  2. 異常處理:捕獲IOException并關閉套接字,防止資源泄漏。

2.3.2TcpEchoClient

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoClient {// 定義一個Socket對象,用于與服務器建立連接private Socket socket = null;// 構造函數,用于初始化客戶端并連接到指定的服務器IP和端口private TcpEchoClient(String serverIp, int serverPort) throws IOException {// 創建一個Socket對象,連接到指定的服務器IP和端口socket = new Socket(serverIp, serverPort);}// 啟動客戶端,開始與服務器進行通信public void start() {// 創建一個Scanner對象,用于從控制臺讀取用戶輸入Scanner scanner = new Scanner(System.in);try (// 獲取Socket的輸入流,用于接收服務器發送的數據InputStream inputStream = socket.getInputStream();// 獲取Socket的輸出流,用于向服務器發送數據OutputStream outputStream = socket.getOutputStream()) {// 創建一個Scanner對象,用于從輸入流中讀取服務器發送的數據Scanner scannerNet = new Scanner(inputStream);// 創建一個PrintWriter對象,用于向輸出流中寫入數據PrintWriter writer = new PrintWriter(outputStream);// 進入一個無限循環,持續與服務器進行通信while (true) {// 從控制臺讀取用戶輸入的數據String request = scanner.next();// 將用戶輸入的數據發送到服務器writer.println(request);// 刷新輸出流,確保數據被發送writer.flush();// 從服務器讀取響應數據String response = scannerNet.next();// 將服務器返回的響應數據打印到控制臺System.out.println(response);}} catch (IOException e) {// 如果發生IO異常,拋出運行時異常throw new RuntimeException(e);}}// 主函數,程序的入口public static void main(String[] args) throws IOException {// 創建一個TcpEchoClient對象,連接到本地服務器的9090端口TcpEchoClient client = new TcpEchoClient("127.0.0.1", 9090);// 啟動客戶端,開始與服務器通信client.start();}
}

?核心思路講解:

  1. Socket連接

    • TcpEchoClient的構造函數中,通過new Socket(serverIp, serverPort)創建一個Socket對象,連接到指定的服務器IP和端口。這個Socket對象將用于后續的通信。

  2. 輸入輸出流

    • start方法中,通過socket.getInputStream()socket.getOutputStream()分別獲取Socket的輸入流和輸出流。輸入流用于接收服務器發送的數據,輸出流用于向服務器發送數據。

  3. 用戶輸入與服務器通信

    • 使用Scanner從控制臺讀取用戶輸入的數據,并通過PrintWriter將數據發送到服務器。

    • 使用Scanner從輸入流中讀取服務器返回的響應數據,并將其打印到控制臺。

  4. 循環通信

    • 通過一個無限循環while (true),客戶端可以持續與服務器進行通信。每次循環中,客戶端都會讀取用戶輸入,發送到服務器,并等待服務器的響應。

  5. 異常處理

    • 如果在通信過程中發生IO異常,代碼會捕獲該異常并拋出運行時異常。

  6. 主函數

    • main函數中,創建一個TcpEchoClient對象,并連接到本地服務器的9090端口。然后調用start方法,啟動客戶端與服務器的通信。

3.小結

今天的分享到這里就結束了,喜歡的小伙伴不要忘記點點贊點個關注,你的鼓勵就是對我最大的支持,加油!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/72823.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/72823.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/72823.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++11新特性 8.final關鍵字、override關鍵字

一.final 用法: 1.修飾函數 只能修飾虛函數,阻止子類重寫這個函數,final關鍵字寫在函數名的后面。 即該虛函數不可以再被重寫。 注意:一般不會在基類中使用,不然沒有意義,因為只能修飾虛函數。 2.修飾…

Python實現網絡通信:Socket模塊與TCP/IP協議全解析

Langchain系列文章目錄 01-玩轉LangChain:從模型調用到Prompt模板與輸出解析的完整指南 02-玩轉 LangChain Memory 模塊:四種記憶類型詳解及應用場景全覆蓋 03-全面掌握 LangChain:從核心鏈條構建到動態任務分配的實戰指南 04-玩轉 LangChai…

click house擴容方案

《ClickHouse擴容方案解析》 當我們談論數據庫的時候,尤其是像ClickHouse這樣專為處理大規模數據分析而設計的列式存儲數據庫時,擴容是一個不可避免的話題。隨著數據量的增長和查詢復雜度的提升,原有的硬件資源可能不足以支撐高效的查詢響應…

【AGI】智譜開源2025:一場AI技術民主化的革命正在到來

智譜開源2025:一場AI技術民主化的革命正在到來 引言:開源,一場技術平權的革命一、CogView4:中文AI生成的里程碑1. 破解漢字生成的“AI魔咒”2. 開源協議與生態賦能 二、AutoGLM:人機交互的范式躍遷1. 自然語言驅動的跨…

java8中young gc的垃圾回收器選型,您了解嘛

在 Java 8 的 Young GC(新生代垃圾回收)場景中,對于 ToC的場景,即需要盡可能減少垃圾回收停頓時間以滿足業務響應要求的場景,以下幾種收集器各有特點,通常 Parnew和 G1 young表現較為出色,下面詳…

【數學 矩陣快速冪】P7108 移花接木|普及+

本文涉及知識點 數學 移花接木 題目背景 遙遠的圣地生長著一棵不為人知的靈樹,或有萬山之高。 但有一日,藏匿于根系的腐朽力量爆發,靈樹已無法支撐往日屹立沖天的高度。 題目描述 靈樹最初的形態可以看作一棵高度為 10 10 10 10 {10}…

2025-03-09 學習記錄--C/C++-PTA 習題10-7 十進制轉換二進制

合抱之木&#xff0c;生于毫末&#xff1b;九層之臺&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、題目描述 ?? 裁判測試程序樣例&#xff1a; #include <stdio.h>void dectobin( int n );int main() {int n;scanf(…

前端 | CORS 跨域問題解決

問題&#xff1a;Access to fetch at http://localhost:3000/save from origin http://localhost:5174 has been blocked by CORS policy: Response to preflight request doesnt pass access control check: No Access-Control-Allow-Origin header is present on the request…

fastapi房產銷售系統

說明&#xff1a; 我希望用fastapi寫幾個接口&#xff0c;查詢房產交易系統的幾條數據&#xff0c;然后在postman里面測試 查詢客戶所有預約記錄&#xff08;含房源信息&#xff09;需要對應銷售經理查詢客戶所有訂單&#xff08;含房源信息&#xff09;統計銷售經理名下所有房…

導軌式ARM工業控制器:組態軟件平臺的“神經中樞”

工業自動化領域&#xff0c;組態軟件平臺扮演著至關重要的角色。它不僅是工業控制系統的“大腦”&#xff0c;更是實現智能化、高效化生產的關鍵工具。而作為組態軟件平臺的硬件支撐&#xff0c;導軌式ARM工控機&#xff08;以下簡稱“工控機”&#xff09;憑借其緊湊的設計、強…

每日一題——矩陣置零問題的原地算法

矩陣置零問題的原地算法 問題描述示例約束條件進階要求 問題分析難點分析解題思路 代碼實現代碼說明 測試用例測試用例 1測試用例 2測試用例 3 總結 問題描述 給定一個 m x n 的矩陣&#xff0c;如果矩陣中的某個元素為 0&#xff0c;則需要將其所在的行和列的所有元素都置為 …

Springboot中的@Value注解:用法與潛在問題探索

在Spring Boot開發中&#xff0c;有個非常實用的注解&#xff0c;那就是Value&#xff01;它可以幫助我們輕松地從配置文件中讀取屬性值。想象一下&#xff0c;在應用程序中管理各種配置&#xff0c;比如數據庫連接信息、服務URL或者API密鑰等&#xff0c;使用Value是多么方便呀…

C++后端服務器開發技術棧有哪些?有哪些資源或開源庫拿來用?

一、 C后臺服務器開發是一個涉及多方面技術選擇的復雜領域&#xff0c;特別是在高性能、高并發的場景下。以下是C后臺服務器開發的一種常見技術路線&#xff0c;涵蓋了從基礎到高級的技術棧。 1. 基礎技術棧 C標準庫 C11/C14/C17/C20&#xff1a;使用現代C特性&#xff0c;如…

25年攜程校招社招求職能力北森測評材料計算部分:備考要點與誤區解析

在求職過程中&#xff0c;能力測評是篩選候選人的重要環節之一。對于攜程這樣的知名企業&#xff0c;其能力測評中的材料計算部分尤為關鍵。許多求職者在備考時容易陷入誤區&#xff0c;導致在考試中表現不佳。本文將深入解析材料計算部分的實際考察方向&#xff0c;并提供針對…

golang進階知識專項-理解值傳遞

在 Go 語言中&#xff0c;所有函數的參數傳遞都是值傳遞&#xff08;Pass by Value&#xff09;。當你將一個變量作為參數傳遞給函數時&#xff0c;實際上傳遞的是該變量的副本&#xff0c;而不是變量本身。理解這一點對于避免常見的編程錯誤至關重要。根據不同的類型&#xff…

RuoYi框架添加自己的模塊(學生管理系統CRUD)

RuoYi框架添加自己的模塊&#xff08;學生管理系統&#xff09; 框架順利運行 首先肯定要順利運行框架了&#xff0c;這個我不多說了 設計數據庫表 在ry數據庫中添加表tb_student 表字段如圖所示 如圖所示 注意id字段是自增的 注釋部分是后面成功后前端要展示的部分 導入…

中級網絡工程師面試題參考示例(1)

一、基礎理論 1. OSI七層模型與TCP/IP四層模型的區別是什么&#xff1f;請舉例說明第三層&#xff08;網絡層&#xff09;和第四層&#xff08;傳輸層&#xff09;的核心協議。 參考答案&#xff1a; OSI七層模型分為物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層、應用…

RHCE9.0版本筆記5:防火墻的本地/遠程登錄方式

一、防火墻登錄方式全景圖 華為防火墻支持多種管理訪問方式&#xff0c;根據安全等級和場景需求可分為&#xff1a; graph LR A[管理方式] --> B[本地登錄] A --> C[遠程登錄] B --> B1(Console) B --> B2(Web) C --> C1(SSH) C --> C2(Telnet) C --> C…

2025最新群智能優化算法:山羊優化算法(Goat Optimization Algorithm, GOA)求解23個經典函數測試集,MATLAB

一、山羊優化算法 山羊優化算法&#xff08;Goat Optimization Algorithm, GOA&#xff09;是2025年提出的一種新型生物啟發式元啟發式算法&#xff0c;靈感來源于山羊在惡劣和資源有限環境中的適應性行為。該算法旨在通過模擬山羊的覓食策略、移動模式和躲避寄生蟲的能力&…

博弈論算法

一、減法游戲 初始有一個數 n。 兩個玩家輪流操作&#xff0c;每次可以減去 1 到 9 之間的任意整數。 將數減到 0 的玩家獲勝。 可以發現規律&#xff1a; 減法游戲只需要判斷當前數取模是否為0&#xff0c;即可快速判斷勝負。 例題&#xff1a; Leetcode 292. Nim 游戲 …