文章目錄
- 前言
- 一、TCP和UDP概述
- 二、UDP
- 1.UDP通信概述
- 2.UDP通信特點
- 3.UDP通信傳輸實作的基石
- 3.1、DatagramPake常用方法
- 3.2、DatagramSocket常用方法
- 4.UDP通信實作原理
- 5.UDP通信原理(代碼實作)
- 總結
前言
繼續今天我們的Java網路編程——TCP和UDP通信
一、TCP和UDP概述
傳輸層通常以TCP和UDP協議來控制端點與端點的通信
| TCP | UDP | |
|---|---|---|
| 協議名稱 | 傳輸控制協議 | 用戶資料包協議 |
| 是否連接 | 面向連接的協議,資料必須要建立連接 | 無連接的協議,每個資料報中都給出完整的地址資訊,因此不需要事先建立發送方和接受方的連接 |
| 是否可靠 | 可靠協議,確保收方完全地獲取發送方所發送的全部資料 | 不可靠協議,發送方所發送的資料報并不一定以相同的次序到達接收方, |
| 可以傳輸的資料大小 | 傳輸資料大小不受限制,一旦連接建立,雙方可以按統一的格式傳輸大的資料 | 傳輸資料時是有大小限制的,每個被傳輸的資料報必須限定在64KB之類 |
| 資料傳輸方式 | IO流 | DatagramPacket |
二、UDP
1.UDP通信概述
UDP協議是一種對等通信的實作,發送方只需要接受方的IP(地址)和Port(埠),就可以直接向它發送資料,不需要線連接,每個程式都可以作為服務器,也可以作為客戶端,UDP是一種無連接的傳輸協議,每個資料報的大小限定在64KB以內,資料報是一個在網路上發送的獨立資訊,它的到達,到達時間以及內容本身等都不能得到保證,這種傳輸方式是無序的,也不能確保絕對的安全可靠,但它很簡單也具有較高的效率,
使用UDP協議進行資料傳輸是,需要將需要傳輸資料定義為資料報(DatagramPaket),在資料報中指明資料所要到達Socket(主機地址和埠號),然后再將資料報發送出去,實體化DatagramPacket時使用引數port和沒有使用引數port的區別在與,提供port的一方可以讓別人主動發送訊息過來,而沒有引數port的則會在發送訊息時自動系結一個本地沒有使用的埠,在接收到發送的資料報(DatagramPaket)時,不僅可以獲取資料,還可以獲得發送方的IP和Port,這樣就可以向發送方發送資料,因此,本質上二者是對等的,
2.UDP通信特點
1、UDP是一種無連接的協議,每個資料報都是一個獨立的資訊,包括完整的原地址或目的地址,它在網路上任何可能的路徑傳往目的地,因此能否到達目的地,到達目的地的時間以及內容的正確性都是不能被保證的,
2、UDP不屬于連接型協議,因而具有資源消耗小,處理速度快的優點,所以通常音頻視頻和普通資料在傳輸時使用UDP較多,因為它們即使偶爾丟一兩個資料包,也不會對接收結果產生太大的影響,
3.UDP通信傳輸實作的基石
UDP通信的Socket使用DatagramSocket類實作,資料報使用DatagramPaket實作
3.1、DatagramPake常用方法
| InetAddress getAddress() | 得到發送方IP地址 |
|---|---|
| int getPort() | 得到發送方的埠號 |
| byte[] getData() | 回傳接識訓沖區,這是一個byte[] |
| int getLength() | 接收位元組的真實大小,通常用于從byte[]中提取出有效資料 |
| int getOffset() | 回傳將要發送或則接收的資料偏移量 |
3.2、DatagramSocket常用方法
| DatagramSocket() | 空建構式 |
|---|---|
| DatagramSocket(int port) | 指定通信埠 |
| void receive(DatagramPaket p) | 接收資料報 |
| void send(DatagramPaket p) | 發送資料報 |
| void close() | 關閉Socket |
4.UDP通信實作原理
無論一個UDP通信程式的功能多么功能齊全,程式多么復雜,七基本結構都是一樣的,都包括以下四個基本步驟
1、在接收端指定一個埠號來創建DatagramSocket,然后創建一個接收資料報(DatagramPaket),使用recevie方法等待發送方請求報文,這將阻塞服務器執行緒
2、在發送方創建一個DatagramSocket,使用接收方的IP和埠來創建發送資料報(DatagramPaket),使用send方法發送,現在接收方的recevie方法被喚醒,同時會將發送方的資料報內容填充到接收方的DatagramPaket中,
3、接收方從發送方的資料報中獲得發送方的IP和埠,使用它們構造一個發送資料報,然后發送給發送方,這樣就實作了發送方和接收方的通信
4、在通信完成后,在客服端和服務端中分別關閉Socket

5.UDP通信原理(代碼實作)
代碼如下(發送端):
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class SendMessage {
public static void main(String[] args) throws Exception {
// 創建發送端Socket物件
DatagramSocket sendSocket = new DatagramSocket();
// 準備需要發送的資料
String message = "hello";
// 創建一個緩沖區
byte[] messageByte = message.getBytes();
// 獲取緩沖區中資料的真實長度
int messageLen = message.length();
// InetAddress實體化獲取本機通信地址
InetAddress address = InetAddress.getLocalHost();
// 設定通信埠號
int port = 12345;
// 打包資料
DatagramPacket sendPacket = new DatagramPacket(messageByte, messageLen, address, port);
// 發送資料
sendSocket.send(sendPacket);
// 發送端等待接收端成功接收資訊后回傳的回應
// 創建一個緩沖區,容量盡量設定大一點因為不知道發送過來的資訊有多大
byte[] recevieByte = new byte[1024*10];
int len = recevieByte.length;
// 接收資料報
DatagramPacket receivePacket = new DatagramPacket(recevieByte, len);
// 接收資料
sendSocket.receive(receivePacket);
// 獲取接收端發送過來的真實長度以及資料
byte[] data = receivePacket.getData();
int length = receivePacket.getLength();
String receiveData = new String(data,0,length);
// 獲取發送者的IP
address = receivePacket.getAddress();
String ip = address.getHostAddress();
System.out.println("接收來自:"+ip+"的資料,內容是:"+receiveData);
// 關閉資源
sendSocket.close();
}
}
代碼如下(接收端):
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class RecevieMessage {
public static void main(String[] args) throws Exception {
// 接收訊息的埠(與發送端保持一致)
int port = 12345;
DatagramSocket recevieSocket = new DatagramSocket(port);
// 設定緩沖區接收發過來的資訊
byte[] receiveByte = new byte[1024*10];
int len = receiveByte.length;
// 接收資料報
DatagramPacket receviePacket = new DatagramPacket(receiveByte, len);
// 接收資料
recevieSocket.receive(receviePacket);
// 獲取實際接收到的資料及其大小
byte[] data = receviePacket.getData();
int length = receviePacket.getLength();
String receiveData = new String(data,0,length);
// 獲取發送者的IP
InetAddress address = receviePacket.getAddress();
String ip = address.getHostAddress();
System.out.println("接收來自:"+ip+"的資料,內容是:"+receiveData);
// 接收端接收到資訊后發送一條確認接收的訊息到發送端
String message = "OK";
byte[] messageByte = message.getBytes();
int messageLength = message.length();
// 從已收到的資料報中獲取IP和port
address = receviePacket.getAddress();
int port1 = receviePacket.getPort();
//構造新資料報
DatagramPacket sendPacket = new DatagramPacket(messageByte, messageLength, address, port1);
// 發送資料
recevieSocket.send(sendPacket);
// 關閉資源
recevieSocket.close();
}
}
發送端輸出結果:

接收端輸出結果:

總結
**注意:**在發送端與接收端啟動測驗時最好最好先啟動接收端,因為這樣才能確保資訊能發送出去,接收端能接收到資訊,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/264827.html
標籤:java
上一篇:詳解java集合框架
下一篇:面向物件---多型
