Java 網路編程 —— 基於 UDP 的數據報和套接字

来源:https://www.cnblogs.com/Yee-Q/archive/2023/06/11/17473218.html
-Advertisement-
Play Games

## UDP 簡介 UDP(User Datagram Protocol,用戶數據報協議)是傳輸層的另一種協議,比 TCP 具有更快的傳輸速度,但是不可靠。UDP 發送的數據單元被稱為 UDP 數據報,當網路傳輸 UDP 數據報時,無法保證數據報一定到達目的地,也無法保證各個數據報按發送的順序到達目 ...


UDP 簡介

UDP(User Datagram Protocol,用戶數據報協議)是傳輸層的另一種協議,比 TCP 具有更快的傳輸速度,但是不可靠。UDP 發送的數據單元被稱為 UDP 數據報,當網路傳輸 UDP 數據報時,無法保證數據報一定到達目的地,也無法保證各個數據報按發送的順序到達目的地,例如:當發送方先發送包含字元串【hello】的數據報,再發送包含字元串【everyone】的數據報時,接收方有可能先接收到字元串【everyone】,再接收到字元串【hello】,也有可能什麼數據也沒有接收到,因為發送方發送的數據有可能在傳輸途中都被丟失了


DatagramPacket 類

DatagramPacket 表示數據報,它的構造方法可以被分為兩種:

  • 創建用來接收數據的 DatagramPacket 對象
  • 創建用來發送數據的 DatagramPacket 對象

兩種構造方法的主要區別是:

  • 用於發送數據的構造方法需要設定數據報到達的目的地的地址
  • 用於接收數據的構造方法無須設定地址

用於接收數據的構造方法包括:

//data:用來存放接收到的數據
//length:指定要接收的位元組數
//offset:指定在data存放數據的起始位置,即data[offset],如果沒有設定,那麼初始位置為data[0]
public DatagramPacket(byte[] data, int length);
public DatagramPacket(bytel data, int offset, int length);

用於發送數據的構造方法包括:

//data:用來存放要發送的數據
//length:指定要發送的位元組數
//offset:指定在data要發送數據的起始位置,即data[offset],如果沒有設定,那麼初始位置為data[0]
//address和port:來指定目的地的地址
public DatagramPacket(byte[] data, int offset, int length, InetAddress address, int port);
public DatagramPacket(byte[] data, int offset, int length, SocketAddress address);
public DatagramPacket(byte[] data, int length, InetAddress address, int port);
public DatagramPacket(byte[] data, int length, SocketAddress address);

DatagramPacket 類包括以下屬性,提供了一系列 get/set 方法來獲取或設置這些屬性:

  • data:表示數據報的數據緩衝區
  • offset:表示數據報的數據緩衝區的起始位置
  • length: 表示數據報的長度
  • address:對於用於發送的數據報,address 屬性表示數據報的目標地址。對於用於接收的數據報,address 屬性表示發送者的地址
  • port:對於用於發送的數據報,port 屬性表示數據報的目標 UDP 埠。對於用於接收的數據報,port 屬性表示發送者的 UDP 埠

DatagramSocket 類

DatagramSocket 類負責接收和發送數據報,每個 DatagramSocket 對象都會與一個本地埠綁定,在此埠監聽發送過來的數據報。在客戶程式中,一般由操作系統為 DatagramSocket 類分配本地埠,這種埠也被稱為匿名埠。在伺服器程式中,一般由程式顯式地為 DatagramSocket 類指定本地埠

DatagramSocket 的構造方法有以下幾種重載形式:

//由操作系統分配的任意的可用埠
DatagramSocket();
//顯式指定本地埠
DatagramSocket(int port);
//同時指定IP和埠
DatagramSocket(int port, InetAddress laddr);
DatagramSocket(SocketAddress bindaddr);

DatagramSocket 的 send 方法負責發送一個數據報,該方法的定義如下:

public void send(DatagramPacket dp) throws IOException

值得註意的是,UDP 提供不可靠的傳輸,如果數據報沒有到達目的地,那麼 send 方法不會拋出任何異常,發送方程式就無法知道數據報是否被接收方接收到,除非雙方通過應用層的特定協議來確保接收方未收到數據報時,發送方能重發數據報

DatagramSocket 的 receive 方法負責接收一個數據報,該方法的定義如下:

public void receive(DatagramPacket datagramPacket) throws IOException

此方法從網路上接收一個數據報,如果網路上沒有數據報,執行該方法的線程就會進入阻塞狀態,直到收到數據報為止。參數 datagramPacket 用來存放接收到的數據報,如果接收的數據報太大,receive 方法會在 datagramPacket 的數據緩衝區記憶體放儘可能多的數據,其餘的數據則丟棄

兩個 TCP Socket 之間存在固定的連接關係,而一個 DatagramSocket 可以與其他任意一個 DatagramSocket 交換數據報。在某些場合,一個 DatagramSocket 可能只希望與固定的另一個遠程 DatagramSocket 通信,從 JDK1.2 開始,DatagramSocket 添加了一些方法,利用這些方法,可以使一個 DatagramSocket 只能與另一個固定的 DatagramSocket 交換數據報

//該方法實際上不建立TCP意義上的連接,但能限制當前DataramSocket只對參數指定的遠程主機和UDP埠收發數據報
public void connect(InetAddress host, int port);
//中止當前DatagramSocket已經建立的連接
public void disconnect();
//當且僅當DatagramSocket已經建立連接時返回所連接的遠程UDP埠,否則返回“-1”
public int getPort();
//當且僅當DatagramSocket已經建立連接時返回所連接的遠程主機的IP地址,否則返回null
public InetAddress getlnetAddress();
//當且僅當DatagramSocket已經建立連接時返回所連接的SocketAddress,否則返回null
public SocketAddress getRemoteSocketAddress();

DatagramSocket 的 close 方法會釋放所占用的本地 UDP 埠,在程式中及時關閉不再需要的 DatagramSocket,這是好的編程習慣


DatagramChannel 類

DatagramChannel 是 SelectableChannel 的子類,可以被註冊到一個 Selector。使用 DatagramChannel,可以使 UDP 伺服器只需用單個線程就能同時與多個客戶通信。DatagramChannel 在預設情況下採用阻塞模式,如果希望該為非阻塞模式,那麼可以調用 configureBlocking(false) 方法

DatagramChannel 類的靜態 open 方法返回一個 DatagramChannel 對象,每個 DatagramChannel 對象都關聯了一個 DatagramSocket 對象,DatagramChannel 對象的 socket 方法返回這個 DatagramSocket 對象

DatagramChannel 對象被創建後,與它關聯的 DatagramSocket 對象還沒有被綁定到任何地址,必須調用 DatagramSocket 對象的 bind 方法來與一個本地地址綁定

DatagramChannel channel = DatagramChannel.open();
DataqramSocket socket = channel.socket();
SocketAddress address = new InetSocketAddress(8000);
socket.bind(address);

與 DatagramSocket 一樣,DatagramChannel 的 connect(SocketAddress remote) 方法使得通道只能對特定的遠程地址收發數據報

DatagramChannel 使用 send 方法發送數據

//把參數src的剩餘數據作為一個數據報寫到通道中,參數target指定目標地址,該方法返回發送的位元組數
public int send(ByteBuffer src, SocketAddress target) throws IOException

DatagramChannel 使用 receive 方法從通道中讀取一個數據報,存放在參數指定的 ByteBufer,並返回數據報的發送方的地址

public SocketAddress receive(ByteBuffer dst) throws IOException

如果 DatagramChannel 工作於阻塞模式,那麼 receive 方法在讀取到數據報之前不會返回。如果 DatagramChannel 工作於非阻寒模式,那麼 receive 方法在沒有數據報可讀取的情況下立即返回 null

DatagramChannel 也可以使用 write 方法發送數據,與 send 方法區別在於:write 方法要求 DatagramChannel 已經建立連接

public int write(ByteBuffer src) throws IOException;
//依次發送ByteBuffer數組中每個ByteBuffer的數據
public long write(ByteBufferl] srcs) throws IOException;
//參數offse指定ByteBuffer數組的起始位置參數,length指定發送的ByteBuffer的數目
public long write(ByteBufferl] srcs, int offset, int length) throws IOException;

DatagramChannel 也可以使用 read 方法接收數據,同樣的,它也要求 DatagramChannel 已經建立連接

public int read(ByteBuffer src) throws IOException;
//把數據報的數據保存到 ByteBuffer 數組中
public long read(ByteBuffer[l srcs) throws IOException;
public long read(ByteBuffer[] srcs, int offset, int length) throws IOException;

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 博客推行版本更新,成果積累制度,已經寫過的博客還會再次更新,不斷地琢磨,高質量高數量都是要追求的,工匠精神是學習必不可少的精神。因此,大家有何建議歡迎在評論區踴躍發言,你們的支持是我最大的動力,你們敢投,我就敢肝 ...
  • List 介面是 Collection 介面的子介面。List 中元素有序,是按照元素的插入順序進行排序的。每個元素都有一個與之關聯的整數型索引(索引從 0 開始),可以根據索引來訪問和操作元素,可以使用普通 for 迴圈遍歷。List 中可以包含重覆的元素。 ...
  • # Go 實現 MySQL 資料庫事務 ## 一、MySQL事務 MySQL事務是指一組資料庫操作,它們被視為一個邏輯單元,並且要麼全部成功執行,要麼全部回滾(撤銷)。事務是資料庫管理系統提供的一種機制,用於確保數據的一致性和完整性。 事務具有以下特性(通常由ACID原則定義): 1. 原子性(At ...
  • 前言 本文主要介紹使用spring boot 配置多個資料庫,即動態資料庫 開始搭建 首先創建一個SpringWeb項目——dynamicdb(spring-boot2.5.7) 然後引入相關依賴lombok、swagger2、mybatis-plus,如下: <?xml version="1.0" ...
  • # todo 列表 - [ ] clang-format - [ ] c++ 整合 # 軟體安裝 略 # 基本的環境搭建 ## 最基本的 vscode 插件 只需要安裝如下兩個插件即可 c/c++ 擴展是為了最基本的代碼提示和調試支持 cmake language support 是為了提示 CMa ...
  • [系列文章目錄和關於我](https://www.cnblogs.com/cuzzz/p/16609728.html) ## 零丶背景 最近有很多想學的,像netty的使用、原理源碼,但是苦於自己對於操作系統和nio瞭解不多,有點無從下手,遂學習之。 ## 一丶網路io的過程 ![image-202 ...
  • 如果某個派生自 QObject 的類重寫 eventFilter 方法,那它就成了事件過濾器(Event Filter)。該方法的聲明如下: virtual bool eventFilter(QObject *watched, QEvent *event); watched 參數是監聽事件的對象,即 ...
  • # Go 連接 MySQL之 MySQL 預處理 ## 一、ChatGPT 關於 MySQL 預處理 的回答 ### 問:什麼是MySQL 的預處理 具體執行過程時什麼 #### ChatGPT 答: MySQL的預處理是一種在執行SQL語句之前,先進行編譯和優化的機制。它將SQL語句分成兩個階段: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...