主頁 > 後端開發 > Java 網路編程 —— 基于 UDP 的資料報和套接字

Java 網路編程 —— 基于 UDP 的資料報和套接字

2023-06-12 07:40:45 後端開發

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;

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/554896.html

標籤:其他

上一篇:Go語言中的init函式: 特點、用途和注意事項

下一篇:返回列表

標籤雲
其他(160785) Python(38219) JavaScript(25492) Java(18216) C(15237) 區塊鏈(8270) C#(7972) AI(7469) 爪哇(7425) MySQL(7246) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5873) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4589) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2435) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1984) 功能(1967) HtmlCss(1961) Web開發(1951) C++(1933) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1881) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Java 網路編程 —— 基于 UDP 的資料報和套接字

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

    uj5u.com 2023-06-12 07:40:45 more
  • Go語言中的init函式: 特點、用途和注意事項

    # 1. 引言 在Go語言中,`init()`函式是一種特殊的函式,用于在程式啟動時自動執行一次。它的存在為我們提供了一種機制,可以在程式啟動時進行一些必要的初始化操作,為程式的正常運行做好準備。 在這篇文章中,我們將詳細探討`init()`函式的特點、用途和注意事項,希望能幫助你更好地理解和使用這 ......

    uj5u.com 2023-06-12 07:40:41 more
  • 【技識訓累】SpringBoot中的簡介與配置【一】

    博客推行版本更新,成果積累制度,已經寫過的博客還會再次更新,不斷地琢磨,高質量高數量都是要追求的,工匠精神是學習必不可少的精神。因此,大家有何建議歡迎在評論區踴躍發言,你們的支持是我最大的動力,你們敢投,我就敢肝 ......

    uj5u.com 2023-06-12 07:40:36 more
  • Go 語言連接資料庫實作增刪改查

    title: "Go 語言連接資料庫實作增刪改查" date: 2023-06-10T18:55:16+08:00 draft: true tags: ["Go"] categories: ["Go"] # Go 連接 MySQL實作增刪改查 ## 一、初始化連接 ### 創建專案 ![](http ......

    uj5u.com 2023-06-12 07:35:18 more
  • Maven常用命令及其作用

    一、Maven常用命令及其作用 Maven的生命周期包括:clean、validate、compile、test、package、verify、install、site、deploy,其中需要注意的是:執行后面的命令時,前面的命令自動得到執行,(其中,也可以跳過其中的步驟,如:test,在mvn i ......

    uj5u.com 2023-06-12 07:35:10 more
  • 【技識訓累】Python中的Pandas庫【三】

    博客推行版本更新,成果積累制度,已經寫過的博客還會再次更新,不斷地琢磨,高質量高數量都是要追求的,工匠精神是學習必不可少的精神。因此,大家有何建議歡迎在評論區踴躍發言,你們的支持是我最大的動力,你們敢投,我就敢肝 ......

    uj5u.com 2023-06-12 07:34:50 more
  • C++ 指標

    # 一、C++ 指標的算術運算 ## 遞增一個指標 我們喜歡在程式中使用指標代替陣列,因為變數指標可以遞增,而陣列不能遞增,因為陣列是一個常量指標。下面的程式遞增變數指標,以便順序訪問陣列中的每一個元素: ``` 實體 #include using namespace std; const int ......

    uj5u.com 2023-06-11 07:17:06 more
  • ImageIO的應用 (AWT和Swing初接觸)

    # ImageIO的應用 # 一、關于IO流 在講imageio之前,我們先來復習一下IO流的使用。 這里我建立一個Java類,用來實作讀取檔案中的內容,并且能夠識別換行,話不多說,上代碼: ```java package com.Evan.demo; import java.io.Buffered ......

    uj5u.com 2023-06-10 07:56:56 more
  • C++面試八股文:了解sizeof運算子嗎?

    某日二師兄參加XXX科技公司的C++工程師開發崗位第10面: > 面試官:了解`sizeof`運算子嗎? > > 二師兄:略微了解(不就是求大小的嘛。。) > > 面試官:請講以下如何使用`sizeof`? > > 二師兄:`sizeof`主要是求變數或者型別的大小。直接使用`sizeof(type ......

    uj5u.com 2023-06-10 07:56:48 more
  • Rust - 介面設計建議之靈活(flexible)

    # Rust - 介面設計建議之靈活(flexible) ## 靈活(flexible) ### 代碼的契約(Contract) - 你寫的代碼包含契約 - 契約: - 要求:代碼使用的限制 - 承諾:代碼使用的保證 - 設計介面時(經驗法則): - 避免施加不必要的限制,只做能夠兌現的承諾 - 增 ......

    uj5u.com 2023-06-10 07:56:43 more