javaSE————網絡編程套接字

網絡編程套接字~~~~~

好久沒更新啦,藍橋杯爆掉了,從今天開始爆更嗷;

1,網絡編程基礎

為啥要有網絡編程呢,我們進行網絡通信就是為了獲取豐富的網絡資源,說實話真的很神奇,想想我們躺在床上,通過網絡,訪問到世界上成千上萬的人做好的網絡資源,我們甚至能看到一輩子都看不到的景色,這些資源本質上都是二進制資源或者是文本資源,我們通過網絡可以讓很多人來訪問,這個就是網絡編程,當年的網絡就是個看報的,誰能想到發展到這樣呢?

網絡編程的概念:網絡上的主機,通過不同的進程,以編程的方式實現網絡通信;

同一個主機下的不同進程實現網絡通信也是網絡編程;

網絡編程的基本概念:

接收端:數據接收端進程,目標主機;

發送端:數據發送端進程,源主機;

收發端:發送接收兩端;

請求:請求數據的發送;

響應:響應數據的發送;

就像我們去餐廳點一份蛋炒飯就是請求,廚師給我們拿來蛋炒飯就是回應;

服務端:提供服務的一方,返回服務資源;

客戶端:獲取服務的一方;


2,Socket套接字

Socket就是套接字,啥是套接字,這名起的,Socket套接字是由系統提供用于網絡通信的技術,是基于TCP/IP協議的網絡通信的基本單元,基于Socket套接字的網絡程序開發就是網絡編程;

Socket套接字主要針對傳輸層協議劃分為三類:

我們這里就學兩個核心協議

1,TCP,有連接,可靠傳輸,面向字節流,全雙工;

2,UDP,無連接,不可靠傳輸,面向數據報,全雙工;

這里的有連接和無連接都是抽象的概念,虛擬上的連接;

TCP協議保存了對端的信息,A和B通信,A和B先建立連接,A保存了B的信息,B也保存了A的信息,他們彼此都知道誰與自己建立的連接,而UDP不保存對方的信息;

可靠傳輸和不可靠傳輸是什么呢?

網絡上,數據的傳輸是會發生丟包的情況的,可能會受到外界的干擾,那么可靠傳輸就能避免這樣的丟包嗎,事實上是不能的,可靠傳輸只是保證盡可能提高傳輸成功的概率,如果出現了丟包,也能感知到,不可靠傳輸的話就是把數據發送之后就不管了,那么這樣的話我們就使用可靠傳輸就好了呀,還要UDP干嘛呢,凡是必有代價,UDP的話速度會更快;

面向字節流和面向數據報呢?

面向字節流:讀寫數據的時候,以字節為單位;

面向數據報:讀寫數據的時候,以一個數據報為單位;

全雙工和半雙工呢?

全雙工:一個通信聯絡,能讀也能寫;

半雙工:只支持單向通信,要么讀,要么寫;

我們使用Socket api來進行網絡編程,我們之前提到計算機中的“文件”有狹義和廣義的概念,硬件設備可以抽象成文件,統一管理;電腦上的網卡就是Socket文件;


3,UDP數據報套接字編程

我們先來介紹UDP需要的API:

DatagramSocket

UDP的Socket用于接收和發送UDP數據報;

構造方法:

方法簽名方法說明
DatagramSocket()創建一個UDP數據報套接字的Socket,綁定到本機任意一個端口,一般用于客戶端
DatagramSocket(int port)創建一個UDP數據報套接字的Socket,綁定到本機指定的端口,一般用于服務端

方法:

方法簽名方法說明
void receive(DatagramPacket p)從此套接字接收數據報,如果沒有收到數據報就會阻塞等待;
void send(DatagramPacket p)從此套接字發送數據報,不會阻塞等待,直接發送;
void close()關閉此數據報套接字

DatagramPacket

datagramPacket是UDP socket發送和接收的數據報;

構造方法:

方法簽名方法說明
DatagramPacket(byte[] bytes, int length)

構造一個DatagramPacket用來接收數據報,接收的數據呢保存在字節數組中,接收指定的長度

DatagramPacket(byte[] bytes, int offset, int length, SocketAddress address)構造一個DatagramPacket用來發送數據報,發送的數據為字節數組,從0開始,到指定長度,address指定制定目的主機的IP和端口號

方法:

方法簽名方法說明
InetAddress? getAddress()

從接收的數據報中,獲取發送端主機IP;或者從發送的數據報中,獲取接收端主機IP;

int getPort()從接收的數據報中,獲取接收端主機的端口號;或者從發送的數據報中,或缺發送端主機的端口號;
byte[] getData()獲取數據報中的數據;?
getSocketAddress()直接獲取到當前數據報的IP和端口號;

?

講完方法了,我們來模擬一個回顯服務器,這里就是模擬,回顯服務器就是自問自答;

我們來用UDP模擬一下:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Socket;
import java.net.SocketException;public class UdpEchoServer {private DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);//指定端口號,讓服務器來使用}public void start() throws IOException {//啟動服務器while(true){//循環一次,就意味著處理了一次請求//1讀取請求并解析DatagramPacket packet = new DatagramPacket(new byte[4090],4090);socket.receive(packet);String request = new String(packet.getData(),0,packet.getLength());//2根據請求計算響應String response = process(request);//3把響應返回給客戶端DatagramPacket packet1 = new DatagramPacket(response.getBytes(),response.getBytes().length,packet.getSocketAddress());socket.send(packet1);//4打印日志System.out.printf("[%s:%d] req: %s, resp: %s\n",packet.getAddress().toString(), packet.getPort(), request, response);}}public String process(String request){return request;}public static void main(String[] args) throws IOException {UdpEchoServer udpEchoServer = new UdpEchoServer(9090);udpEchoServer.start();}
}

模擬服務器:難點用注釋標注了,看不明白就來私信我!?

接下來實現客戶端代碼:

import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null;private String SeverIp;private int SeverPort;public UdpEchoClient(String IP,int port) throws SocketException {this.SeverIp = IP;this.SeverPort = port;socket = new DatagramSocket();}public void start() throws IOException {Scanner scanner = new Scanner(System.in);while(true){System.out.println("請輸入要發送的內容");while(!scanner.hasNext()){break;}String request = scanner.nextLine();DatagramPacket datagramPacket = new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(SeverIp),SeverPort);socket.send(datagramPacket);DatagramPacket datagramPacket1 = new DatagramPacket(new byte[4090],4090);socket.receive(datagramPacket1);String response = new String(datagramPacket1.getData(),0,datagramPacket1.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient udpEchoClient = new UdpEchoClient("127.0.0.1",9090);udpEchoClient.start();}}

我們把兩個代碼的都運行下?

客戶端

服務器


4,TCP流套接字編程

接下來我們來實現TCP的網絡編程,還是先來學習一下方法:

SeverSocket

SeverSocket呢是創建TCP服務端Socket的ApI;

構造方法:

方法簽名方法說明
SeverSocket(int port)創建一個服務端流套接字Socket,并綁定到指定端口

方法:

方法簽名方法說明
Socket accept()開始監聽指定端口(創建時綁定的端口),有客戶端連接后,返回一個服務端Socket對象,并基于該Socket建立與客戶端的連接,否則阻塞等待;
void close()關閉此套接字;

Socket

socket是客戶端Socket,或服務端中接收到客戶端建立連接(accept)的請求后,返回的服務端Socket;

構造方法:

方法簽名方法說明
Socket(String host,int port)創建一個客戶端流套接字Socket,并與對應IP的主機上,對應端口的進程建立連接;

方法:

方法簽名方法說明
inerAddress? getInetAddress()返回套接字所連接的地址
inputStream? getInputStream()返回此套接字的輸入流
OutputStream? getOutputStream()返回此套接字的輸出流

服務端

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;public class TcpEchoServer {private ServerSocket serverSocket = null;public TcpEchoServer(int port) throws IOException {serverSocket = new ServerSocket(port);}public void start() throws IOException {System.out.println("啟動服務器");ExecutorService executorService = Executors.newCachedThreadPool();while(true){Socket socketClient = serverSocket.accept();executorService.submit(()->{try {processConnection(socketClient);} catch (IOException e) {throw new RuntimeException(e);}});}}public void processConnection(Socket socketClient) throws IOException {System.out.println("客戶端上線"+ socketClient.getInetAddress()+socketClient.getPort());try(InputStream inputStream = socketClient.getInputStream();OutputStream outputStream = socketClient.getOutputStream()){Scanner scanner = new Scanner(inputStream);PrintWriter printWriter = new PrintWriter(outputStream);while (true){if(!scanner.hasNext()){System.out.println("客戶端下線"+ socketClient.getInetAddress()+socketClient.getPort());break;}String request = scanner.nextLine();String response = process(request);printWriter.println(response);printWriter.flush();System.out.printf("[%s:%d] req: %s, resp: %s\n", socketClient.getInetAddress(), socketClient.getPort(),request, response);}}}public String process(String request){return request;}public static void main(String[] args) throws IOException {TcpEchoServer tcpEchoServer = new TcpEchoServer(9090);tcpEchoServer.start();}
}


這里引入線程池來處理多個請求,避免其他請求發來處理不了的情況;

客戶端:
?

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoClient {private Socket socket = null;public TcpEchoClient(String IP,int port) throws IOException {socket = new Socket(IP,port);}public void start() throws IOException {Scanner scanner = new Scanner(System.in);try(InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()){Scanner scanner1 = new Scanner(inputStream);PrintWriter printWriter = new PrintWriter(outputStream);while(true){System.out.println("請輸入要發送的信息");String request = scanner.nextLine();printWriter.println(request);printWriter.flush();String response = scanner1.nextLine();System.out.println(response);}}}public static void main(String[] args) throws IOException {TcpEchoClient tcpEchoClient = new TcpEchoClient("127.0.0.1",9090);tcpEchoClient.start();}
}

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

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

相關文章

MySQL性能調優(三):MySQL中的系統庫(mysql系統庫)

文章目錄 MySQL性能調優數據庫設計優化查詢優化配置參數調整硬件優化 MySQL中的系統庫1.5.Mysql中mysql系統庫1.5.1.權限系統表1.5.2.統計信息表1.5.2.1.innodb_table_stats1.5.2.2.innodb_index_stats 1.5.3.日志記錄表1.5.3.1. general_log1.5.3.2. slow_log 1.5.4.InnoDB中的…

多個路由器互通(靜態路由)無單臂路由(簡單版)

多個路由器互通(靜態路由)無單臂路由(簡單版) 開啟端口并配ip地址 維護1 Router>en Router#conf t Router(config)#int g0/0 Router(config-if)#no shutdown Router(config-if)#ip address 192.168.10.254 255.255.255.0 Ro…

關于 AI驅動的智慧家居、智慧城市、智慧交通、智慧醫療和智慧生活 的詳細解析,涵蓋其定義、核心技術、應用場景、典型案例及未來趨勢

以下是關于 AI驅動的智慧家居、智慧城市、智慧交通、智慧醫療和智慧生活 的詳細解析,涵蓋其定義、核心技術、應用場景、典型案例及未來趨勢: 一、AI智慧家居 1. 定義與核心功能 定義:通過AI與物聯網(IoT)技術&#…

【ESP32|音頻】一文讀懂WAV音頻文件格式【詳解】

簡介 最近在學習I2S音頻相關內容,無可避免會涉及到關于音頻格式的內容,所以剛開始接觸的時候有點一頭霧水,后面了解了下WAV相關內容,大致能夠看懂wav音頻格式是怎么樣的了。本文主要為后面ESP32 I2S音頻系列文章做鋪墊&#xff0…

端側大模型綜述On-Device Language Models: A Comprehensive Review

此為機器翻譯,僅做個人學習使用 設備端語言模型:全面回顧 DOI:10.48550/arXiv.2409.00088 1 摘要 大型語言模型 (LLM) 的出現徹底改變了自然語言處理應用程序,由于減少延遲、數據本地化和個性化用戶體驗…

推流265視頻,網頁如何支持顯示265的webrtc

科技發展真快,以前在網頁上(一般指谷歌瀏覽器),要顯示265的視頻流,都是很雞肋的辦法,要么轉碼,要么用很慢的hls,體驗非常不好,而今谷歌官方最新的瀏覽器已經支持265的web…

redis的sorted set的應用場景

Redis 的 Sorted Set(有序集合,簡稱 ZSet) 結合了 Set 的去重特性 和 按分數(score)排序 的特性,非常適合需要 高效排序 或 范圍查詢 的場景。以下是它的典型應用場景及示例: 實時排行榜 場景&…

18-21源碼剖析——Mybatis整體架構設計、核心組件調用關系、源碼環境搭建

學習視頻資料來源:https://www.bilibili.com/video/BV1R14y1W7yS 文章目錄 1. 架構設計2. 核心組件及調用關系3. 源碼環境搭建3.1 測試類3.2 實體類3.3 核心配置文件3.4 映射配置文件3.5 遇到的問題 1. 架構設計 Mybatis整體架構分為4層: 接口層&#…

未啟用CUDA支持的PyTorch環境** 中使用GPU加速解決方案

1. 錯誤原因分析 根本問題:當前安裝的PyTorch是CPU版本,無法調用GPU硬件加速。當運行以下代碼時會報錯:model YOLO("yolov8n.pt").to("cuda") # 或 .cuda()2. 解決方案步驟 步驟1:驗證CUDA可用性 在Pyth…

JVM-基于Hotspot

前言 Java虛擬機(Java Virtual Machine簡稱JVM)是運行所有Java程序的抽象計算機,是Java語言的運行環境,其主要任務為將字節碼裝載到內部,解釋/編譯為對應平臺上的機器指令執行。 Java虛擬機規范定義了一個抽象的——…

智能合約安全審計平臺——可視化智能合約漏洞掃描

目錄 可視化智能合約漏洞掃描 —— 理論、實踐與安全保障1. 引言2. 理論背景與漏洞原理2.1 智能合約簡介2.2 常見漏洞類型2.3 漏洞掃描與安全評估原理3. 系統架構與工作流程3.1 系統總體架構3.2 模塊說明4. 漏洞掃描流程詳解4.1 代碼上傳與靜態解析4.2 漏洞模式檢測4.3 風險評估…

【MySQL數據庫】數據類型詳解

目錄 數據類型tinyint類型(整形)bit類型小數浮點數 float、doubledecimal 字符串類型charvarcharchar與varchar的比較 日期時間類型enum和set總結 數據類型 tinyint類型(整形) 例: mysql> create table tt1(num tinyint);mysql> insert into tt1 values(1)…

咪咕MG101_晨星MSO9380芯片_安卓5.1.1_免拆卡刷固件包

咪咕MG101_晨星MSO9380芯片_安卓5.1.1_免拆卡刷固件包(內有教程) 刷機教程簡單說明: 1、把下載好的刷機包,U盤里建立一個upgrade文件夾,固件放入此文件夾里,放入U盤中,注意升級包為壓縮包不要對…

CS61A:STRING REPRESENTATION

Python 規定所有對象都應該產生兩種不同的字符串表示形式:一種是人類可解釋的文本,另一種是 Python 可解釋的表達式。字符串的構造函數 str 返回一個人類可讀的字符串。在可能的情況下,repr 函數會返回一個計算結果相等的 Python 表達式。rep…

LangChain緩存嵌入技術完全指南:CacheBackedEmbedding原理與實踐(附代碼示例)

一、嵌入緩存技術背景與應用場景 1.1 為什么需要嵌入緩存? 算力消耗問題:現代嵌入模型(如text-embedding-3-small)單次推理需要約0.5-1秒/文本 資源浪費現狀:實際業務中約30%-60%的文本存在重復計算 成本壓力&#…

精益數據分析(3/126):用數據驅動企業發展的深度解析

精益數據分析(3/126):用數據驅動企業發展的深度解析 大家好!一直以來,我都堅信在當今競爭激烈的商業環境中,數據是企業獲得競爭優勢的關鍵。最近深入研究《精益數據分析》這本書,收獲頗豐&…

wpf ScaleTransform

在WPF中,ScaleTransform是用于實現元素縮放的核心類,屬于System.Windows.Media命名空間下的變換類型。以下是其主要特性與使用方式的總結: ?核心屬性? ?縮放比例? ScaleX:水平方向縮放比例(默認1.0,即…

用純Qt實現GB28181協議/實時視頻/云臺控制/預置位/錄像回放和下載/事件訂閱/語音對講

一、前言 在技術的長河中探索,有些目標一旦確立,便如同璀璨星辰,指引著我們不斷前行。早在2014年,我心中就種下了用純Qt實現GB28181協議的種子,如今回首,一晃十年已逝,好在整體框架和邏輯終于打…

0x01、Redis 主從復制的實現原理是什么?

Redis 主從復制概述 Redis 的主從復制是一種機制,允許一個主節點(主實例)將數據復制到一個或多個從節點(從實例)。通過這一機制,從節點可以獲取主節點的數據并與之保持同步。 復制流程 開始同步&#xf…

整活 kotlin + springboot3 + sqlite 配置一個 SQLiteCache

要實現一個 SQLiteCache 也是很簡單的只需要創建一個 cacheManager Bean 即可 // 如果配置文件中 spring.cache.sqlite.enable false 則不啟用 Bean("cacheManager") ConditionalOnProperty(name ["spring.cache.sqlite.enable"], havingValue "t…