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
標籤:其他
下一篇:返回列表
