【Java】TCP網絡編程:從可靠傳輸到Socket實戰

活動發起人@小虛竹 想對你說:

這是一個以寫作博客為目的的創作活動,旨在鼓勵大學生博主們挖掘自己的創作潛能,展現自己的寫作才華。如果你是一位熱愛寫作的、想要展現自己創作才華的小伙伴,那么,快來參加吧!我們一起發掘寫作的魅力,書寫出屬于我們的故事。我們誠摯邀請你參加為期14天的創作挑戰賽!

提醒:在發布作品前,請將不需要的內容刪除。

?各位看官,大家早安午安晚安呀~~~

如果您覺得這篇文章對您有幫助的話

歡迎您一鍵三連,小編盡全力做到更好
歡迎您分享給更多人哦

今天我們來學習【Java】TCP網絡編程:從可靠傳輸到Socket實戰

目錄

1.首先我們再說一下TCP和UDP的區別和相同點

2.連接:通信雙方都會記錄對方的信息

3.主要是兩個api ServerSocket和Socket

4.TCP服務端實戰代碼演示

5.TCP客戶端實戰代碼演示


TCP的socket的api的差異很大,但是和前面的IO有很大的關聯

1.首先我們再說一下TCP和UDP的區別和相同點

1.TCP是有連接的,UDP無連接(這一點可以在代碼中體現)

2.TCP是面向字節流流的,UDP是面向數據報的

3.TCP是可靠傳輸的,UDP是不可靠傳輸的(這一點在代碼中體現不出來)

4.TCP和UDP都是全雙工的

2.連接:通信雙方都會記錄對方的信息

UDP:每次發送數據報都要指定對方的地址(UDP沒有存儲這個信息)

一張圖

TCP:不需要(不過需要內核自動和客戶端建連接(TCP的三次握手,后面我會進行講解)這個過程是系統內核自動完成的)

對于應用程序來說,客戶端是發起“建立連接”

服務器這邊:把內核中建立好的連接拿到應用程序里面()

這個ServerSocket只負責綁定端口號,然后通過accept方法 把建立好的連接拿過來(但是一瞬間有很多連接的話,就像生產者消費者模型里面只能進行阻塞等待)

3.主要是兩個api ServerSocket和Socket

ServerSocket是給服務器用的類,使用這個類用來綁定端口號(這個類負責把系統內核里面已經建立好的連接從隊列里面拿過來,)

Socket:既會給服務器使用的類,也會給客戶端使用,通過socket這個對象和客戶端進行交互

(這兩個類都是用來表示socket文件的,抽象了網卡這樣的硬件設備)

4.TCP服務端實戰代碼演示

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.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TcpEchoServer {      // 讀取用Scanner ,發送用PrintWriter//  1.首先serverSocket調用系統API把連接拿過來,然后交給socket//  我們就有了socket這個對象,這個時候我們就可以宣布這個客戶端成功和我們服務器建立了聯系并且我們拿到了// 2.然后我們通過字節流把數據從socket抽象的文件里面讀取到,用try包起來,用scanner從流里面讀取// 3. 我們拿到字符串進行響應// 4. 把返回的字符串通過字節流(我們的字符串通過字符流轉換成字節流)寫回去// 5. 把信息打印出來private ServerSocket serverSocket = null;public TcpEchoServer(int serverPort) throws IOException {// 利用這個系統API從內核中取到已經建立好的連接// 這個和客戶端構造的socket完全不一樣,客戶端的那個是我們已經拿到的連接serverSocket = new ServerSocket(serverPort);  // 服務器自己分配端口號,}public void start() throws IOException {System.out.println("服務器啟動");// 把隊列里面建立好的連接拿過來while(true){   //  要一直不斷地從那個內核里面不斷地拿我們已經建立好的連接!!!Socket Clientsocket = serverSocket.accept();/* //創建一個新的線程把這個請求進行響應Thread t = new Thread(() ->{possessCollection(Clientsocket);});t.start();*/// 但是線程池是更好一點點的選擇ExecutorService service = Executors.newCachedThreadPool();service.submit(() ->{possessCollection(Clientsocket);});}}public void possessCollection(Socket Clientsocket){   //System.out.printf("[%s,%d] 客戶端上線\n" , Clientsocket.getInetAddress(),Clientsocket.getPort());// 把端口號和IP拿到try(        InputStream inputStream = Clientsocket.getInputStream();   //  這里要用 "  ;  "OutputStream outputStream = Clientsocket.getOutputStream()){// 客戶可能等會還會繼續發送請求(我們循環處理)Scanner scanner = new Scanner(inputStream);//每一次讀一次緩沖區,緩沖區里面的東西就少一次,都被我讀出來了嘛while(true){if(!scanner.hasNext()){// 用戶不再輸入的時候,就直接跳出循環!!!,一直等待用戶輸入System.out.printf("[%s,%d] 客戶端下線\n" , Clientsocket.getInetAddress(),Clientsocket.getPort());break;}String request = scanner.next();// 拿到字符串進行響應String response = process(request);// 拿到響應//4. 拿到字符串的響應,然后我們通過字符流轉字節流傳遞出去PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(response);// 此處的println不是寫到控制臺了,而是寫到outputStream的流對象了,也就是寫入到ClientSocket里面了// 自然這個數據也是通過網卡發出去了printWriter.flush();// 再刷新一下緩存,防止沒有發出去,// 總結:  發送和接收數據都是通過socket文件的字節流輸入輸出來實現,用scanner讀字節流,用printWriter寫字符串// 5.打印一下交互過程System.out.printf("[%s,%d] req=%s resp=%s\n",Clientsocket.getInetAddress(),Clientsocket.getPort(),request,response);}}catch(IOException e){e.printStackTrace();}finally{try {Clientsocket.close();} catch (IOException e) {throw new RuntimeException(e);}}}private String process(String request) {  // 回顯服務器return request;}public static void main(String[] args) throws IOException {TcpEchoServer tcpEchoServer = new TcpEchoServer(9090);tcpEchoServer.start();}}

但是這里面會出現兩個問題

問題一:為什么我們的ServerSocket對象沒有進行close操作,但是Socket對象卻需要close操作呢?這樣不會出現文件資源泄露嗎?

首先我們需要知道什么時候回造成文件資源泄露?

直頻繁申請但是一直不釋放就會(什么文件的表項啥的)

但是ServerSocket對象從頭到尾只創建過一次對象,而且一直在把內核中建立的連接拿到。所以說ServerSocket這個對象的生命周期是是伴隨著進程消失的(因此不需要特地的進行回收,等到進程解釋JVM會把這個進程里面的東西一起回收了)

但是?

問題二:等待我們寫完客戶端的代碼之后進行講述

如果啟動多個客戶端和服務器進行連接(就不行了,這個服務器一直在等待客戶端進行輸入,我們就需要多個線程并發拿到這個連接)

但是頻繁地創建和銷毀線程也會有很大開銷,線程池是更好一點點選擇

5.TCP客戶端實戰代碼演示

import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;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 {/*** 1.隨機分配一個端口的發出信息(我們要把服務器的IP地址和端口號給搞進去)* 2.我們循環輸入一個字符串,把這個字符串用字符流轉換成字節流寫到socket抽象的文件里面* 3.然后我們接收響應(不像服務器,我們又不需要進行處理)* 4.我們直接通過Scanner把字節流里面的內容讀出來就好了*/private Socket socket = null;public TcpEchoClient(String serverIP,int serverPort) throws IOException {socket = new Socket(serverIP,serverPort);}public void start(){System.out.println(" -> ");Scanner scanner = new Scanner(System.in);try(OutputStream outputStream = socket.getOutputStream();InputStream inputStream = socket.getInputStream()){while(true){/* if(!scanner.hasNext()){  // 用戶不想輸入了,就直接退出了break;   不需要這個}*///     * 2.我們循環輸入一個字符串,把這個字符串用字符流轉換成字節流寫到socket抽象的文件里面String request = scanner.next();PrintWriter printWriter = new PrintWriter(outputStream);  // 這些流盡量都放到try()里面printWriter.println(request);printWriter.flush();// 一定不要忘記刷新緩存區'//      * 4.我們直接通過Scanner把字節流里面的內容讀出來就好了Scanner scannerNetwork = new Scanner(inputStream); // 這個Scanner盡量也是放到try()里面String response = scannerNetwork.next();System.out.println(response);}}catch(IOException e){e.printStackTrace();}}public static void main(String[] args) throws IOException {TcpEchoClient tcpEchoClient = new TcpEchoClient("127.0.0.1",9090);tcpEchoClient.start();}
}

上述就是【Java】TCp網絡編程:TCP網絡編程:從可靠傳輸到Socket實戰的全部內容啦

能看到這里相信您一定對小編的文章有了一定的認可。

有什么問題歡迎各位大佬指出
歡迎各位大佬評論區留言修正~~

您的支持就是我最大的動力???!!!

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

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

相關文章

藍橋杯C++基礎算法-0-1背包

這段代碼實現了一個經典的0-1 背包問題的動態規劃解法。0-1 背包問題是指給定一組物品,每個物品有其體積和價值,要求在不超過背包容量的情況下,選擇物品使得總價值最大。以下是代碼的詳細思路解析: 1. 問題背景 給定 n 個物品&am…

html5炫酷的科技感3D文字效果實現詳解

炫酷的科技感3D文字效果實現詳解 這里寫目錄標題 炫酷的科技感3D文字效果實現詳解項目概述核心技術實現1. 3D文字效果2. 故障藝術效果(Glitch Effect)3. 動態網格背景4. 掃描線效果5. 粒子效果 性能優化考慮技術難點與解決方案項目總結擴展優化方向 項目…

車道保持中車道線識別

需要讓小車保持車道行駛,首先需要進行車道線識別。 也可參看論文(上傳到資源里):自動駕駛汽車車道檢測與預測的技術解析-基于圖像處理和Hough變換的方法 1 車道識別流程 想進行車道線識別,并且希望在圖像中選擇一個特…

英偉達有哪些支持AI繪畫的 工程

英偉達在AI繪畫領域布局廣泛,其自研工具與第三方合作項目共同構建了完整的技術生態。以下是其核心支持AI繪畫的工程及合作項目的詳細介紹: 一、英偉達自研AI繪畫工具 1. GauGAN系列 技術特點:基于生成對抗網絡(GAN)&…

驅動開發的引入

1.引入 Linux內核的整體架構本就非常龐大,其包含的組件也非常多。而我們怎樣把需要的部分都包含在內核中呢? 一種方法是把所有需要的功能都編譯到Linux內核中。這會導致兩個問題,一是生成的內核會很大,二是如果我們要在現有的內核中新增或刪…

AI日報 - 2025年3月24日

🌟 今日概覽(60秒速覽) ▎🤖 AGI突破 | Lyra生物序列建模架構效率驚人 在100生物任務中達最優,推理速度提升高達12萬倍 ▎💼 商業動向 | OpenAI用戶破4億,Meta與Reliance探討AI合作 生態擴展與全…

VMware上對CentOS7虛擬機進行磁盤擴容、縮容

在VMware 17 Pro上對CentOS 7虛擬機進行磁盤擴容,同時保證原先部署的軟件正常使用,可以按照以下步驟進行操作: 一、擴容 步驟一:關閉虛擬機并在VMware中擴展磁盤容量 關閉虛擬機:在VMware Workstation 17 Pro中&…

.gitignore使用指南

.gitignore使用指南 目錄 什么是.gitignore為什么需要.gitignore如何創建.gitignore文件.gitignore文件的語法規則 忽略單個文件忽略目錄忽略特定類型的文件不忽略特定文件或目錄遞歸匹配 示例.gitignore文件注意事項更多特殊場景匹配規則 忽略多個特定后綴的文件忽略特定目錄…

OpenCV旋轉估計(3)幫助構建一個最大生成樹(Maximum Spanning Tree)函數findMaxSpanningTree()

操作系統:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 編程語言:C11 算法描述 cv::detail::findMaxSpanningTree 是 OpenCV 中用于圖像拼接工作流的一個函數,它幫助構建一個最大生成樹(Maximum Spanni…

Android在kts中簡單使用AIDL

Android在kts中簡單使用AIDL AIDL相信做Android都有所了解,跨進程通信會經常使用,這里就不展開講解原理跨進程通信的方式了,最近項目換成kts的方式,于是把aidl也換成了統一的方式,其中遇到了很多問題,這里…

論文閱讀:2024-NAACL Semstamp、2024-ACL (Findings) k-SemStamp

總目錄 大模型安全相關研究:https://blog.csdn.net/WhiffeYF/article/details/142132328 Semstamp: A semantic watermark with paraphrastic robustness for text generation https://aclanthology.org/2024.naacl-long.226/ k-SemStamp: A Clustering-Based Semantic Wate…

物化視圖詳解:數據庫性能優化的利器

物化視圖(Materialized View)作為數據庫性能優化的核心手段,通過預計算和存儲查詢結果,顯著提升了復雜查詢的效率。本文將深入剖析物化視圖的工作原理、應用場景及最佳實踐,幫助企業在合適的場景中充分發揮其性能優勢。…

快速入手:Nacos融合SpringCloud成為注冊配置中心

快速入手:Nacos融合SpringCloud成為注冊配置中心 前言安裝Nacos項目搭建添加配置啟動類添加注解運行項目服務調用RestTemplate 模式FeignClient 模式 Gateway 網關 前言 Spring Cloud是一系列框架的集合,提供了微服務架構下的各種解決方案,如…

2025年2月-3月后端go開發找工作感悟

整體感悟 目標 找工作首先要有一個目標,這個目標盡可能的明確,比如我要字節、拼多多之類的公司,還是要去百度、滴滴這樣的,或者目標是創業公司。但是這個目標是會動態調整的,有可能我們的心態發生了變化,一…

Python | 如何在Pandas中刪除常量列

在數據分析中,經常會遇到數據集中始終具有常量值的列(即,該列中的所有行包含相同的值)。這樣的常量列不提供有意義的信息,可以安全地刪除而不影響分析。 如: 在本文中,我們將探索如何使用Pyth…

5.高頻加熱的原理與常用集成電路介紹

一、高頻加熱的類型 利用高頻電源加熱通常由兩種方法:電介質加熱(被加熱物體絕緣)與感應加熱(被加熱物體導電),詳細解釋如下: 電介質加熱(利用高頻電壓的高頻電場導致物體自身分子摩…

串口通信與Modbus通信的區別和聯系

一、定義與定位 1?、串口通信? 是物理層的硬件接口標準,用于實現設備間的?串行數據傳輸?,常見類型包括RS-232、RS-485和RS-422?35。其功能是完成并行數據與串行信號的轉換,并定義電氣特性(如電平、傳輸速率)?。…

Linux生產者消費者模型

Linux生產者消費者模型 Linux生產者消費者模型詳解生產者消費者模型生產者消費者模型的概念生產者消費者模型的特點生產者消費者模型優點 基于BlockingQueue的生產者消費者模型基于阻塞隊列的生產者消費者模型模擬實現基于阻塞隊列的生產消費模型基礎實現生產者消費者步調調整條…

【中文翻譯】第9章-The Algorithmic Foundations of Differential Privacy

由于GitHub項目僅翻譯到前5章,我們從第6章開始通過大語言模型翻譯,并導出markdown格式。 大模型難免存在錯漏,請讀者指正。 教材原文地址:https://www.cis.upenn.edu/~aaroth/Papers/privacybook.pdf 9 差分隱私與計算復雜度 到目…

【AI大模型】搭建本地大模型GPT-NeoX:詳細步驟及常見問題處理

搭建本地大模型GPT-NeoX:詳細步驟及常見問題處理 GPT-NeoX是一個開源的大型語言模型框架,由EleutherAI開發,可用于訓練和部署類似GPT-3的大型語言模型。本指南將詳細介紹如何在本地環境中搭建GPT-NeoX,并解決過程中可能遇到的常見問題。 1. 系統要求 1.1 硬件要求 1.2 軟…