Java UDP通信 講解與簡單實現

UDP協議

UDP提供了一種無需建立連接就能發送數據的方式,即“喊話”,他不管接收者是否收到,只管發送,優點是佔用資源少 不用像tcp那樣建立可靠連接

DatagramSocket類

使用DatagramSocket類我們可以簡單的封裝一個socket,但是不同的是,這個socket不是像TCP的socket那樣建立可靠連接,這個socket是一個抽象的“管道”,負責發送數據,而不維護流,也不維護連接狀態

抽象的講,創建DatagramSocket對象,相當於我們架起天線,準備接受,或者發送

接收端DatagramSocket的構造

在創建接收端的DatagramSocket對象時,需要指定兩個參數,即偵聽的端口和ip,默認是localhost

InetAddress addr = InetAddress.getByName("localhost");
int port = 54321;
DatagramSocket recv_socket = new DatagramSocket(port, addr);

發送端DatagramSocket的構造

在創建發送端的DatagramSocket對象時,我們不需要指定參數,因爲目標主機的信息包含在數據裏面,要在數據包裏面指定,這個稍後會提到

DatagramSocket send_socket = new DatagramSocket();

DatagramPacket類

DatagramPacket類是抽象的數據包類,DatagramSocket正是用來發送或者接受DatagramPacket對象的管道。

如果把DatagramSocket比作天線,那麼DatagramPacket就是發送的電磁波

和DatagramSocket類似,發送端和接收端的配置方式都不一樣,接下來看一下如何構造DatagramPacket對象

接收端DatagramPacket對象的構造

因爲接收端DatagramSocket已經指定了偵聽的端口和ip,所以這個包只負責存數據,即我們只需要指定一個字節數組,並且傳遞給DatagramPacket,即可指定數據存放的DatagramPacket包

byte[] rbuf = new byte[1024];
DatagramPacket data = new DatagramPacket(rbuf, 1024);

發送端DatagramPacket對象的構造

發送端DatagramPacket就比較特殊,因爲我們的發送socket只負責發送,不管發到哪裏,而目標地址是寫在UDP包裏面的,所以我們不僅要指定數據所在的字節數組,還要傳入目標主機的ip和端口

// 發送給服務端
String send_msg = "hello\r\n";
byte[] sbuf = send_msg.getBytes();
int send_port = 54321;
InetAddress addr = InetAddress.getByName(ip);
DatagramPacket resp = new DatagramPacket(sbuf, sbuf.length, addr, send_port);

例子:本地UDP通信

我們使用本機的54321端口作爲服務端的接收端口,54322端口作爲客戶端的接收端口,避免自己發自己導致數據泛洪

在這裏插入圖片描述

服務端:UDPServer

import java.net.*;

public class UDPServer {
	
	int send_port = 54322;
	int recv_port = 54321;
	String ip = "localhost";
	
	public UDPServer() {
		
	}
	
	public UDPServer(String ip, int sport, int rport) {
		this.ip = ip;
		this.send_port = sport;
		this.recv_port = rport;
	}
	
	public void Lisent() throws Exception {
		
		// 創建發送和接收的UDPsocket
		DatagramSocket send_socket = new DatagramSocket();
		DatagramSocket recv_socket = new DatagramSocket(recv_port, InetAddress.getByName(ip));
		
		// 接收數據的DatagramPacket對象
		byte[] buf = new byte[1024];
		DatagramPacket data = new DatagramPacket(buf, 1024);
		while(true) {
			// 接受數據
			recv_socket.receive(data);	
			String msg = new String(buf);
			System.out.println("[服務端] 接受到客戶端信息: " + msg);
			String rstr = "服務端收到消息" + msg;
			byte[] rbuf = rstr.getBytes();
			
			// 發送響應信息
			InetAddress caddr = data.getAddress();	// 客戶端ip
			// 創建發送數據的DatagramPacket對象 需要指定目標ip和端口
			DatagramPacket resp = new DatagramPacket(rbuf, rbuf.length, caddr, send_port);
			send_socket.send(resp);
			
		}
	}
	
	public static void main(String[] args) throws Exception {
		UDPServer server = new UDPServer("127.0.0.1", 54322, 54321);
		server.Lisent();
	}
	
}

客戶端:UDPClient

import java.net.*;
import java.util.*;

public class UDPClient {
	
	String ip = "localhost";
	int send_port = 54322;
	int recv_port = 54321;
	DatagramSocket send_socket = null;
	DatagramSocket recv_socket = null;

	UDPClient() {
		
	}
	
	UDPClient(String ip, int sport, int rport) throws Exception {
		this.ip = ip;
		this.send_port = sport;
		this.recv_port = rport;
		send_socket = new DatagramSocket();
		recv_socket = new DatagramSocket(recv_port, InetAddress.getByName(ip));
	}
	
	public void Send(String send_msg) throws Exception {
		
		// 發送給服務端
		byte[] sbuf = send_msg.getBytes();
		DatagramPacket resp = new DatagramPacket(sbuf, sbuf.length, InetAddress.getByName(ip), send_port);
		send_socket.send(resp);
		
		// 接受數據
		byte[] rbuf = new byte[1024];
		DatagramPacket data = new DatagramPacket(rbuf, 1024);
		recv_socket.receive(data);	
		String msg = new String(rbuf);
		System.out.println("[客戶端] 接受到服務端信息: " + msg);
		
	}
	
	public static void main(String[] args) throws Exception {
		UDPClient client = new UDPClient("127.0.0.1", 54321, 54322);
		while(true) {
			client.Send(new Scanner(System.in).nextLine());
		}
	}
	
}

結果

客戶端輸入發送,服務端回顯:
在這裏插入圖片描述

服務端顯示:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章