Java模擬UDP通信示例代碼
Java基礎(chǔ):模擬UDP通信
1、一次發(fā)送,一次接收
1.1、發(fā)送方
// 發(fā)送端,不需要連接服務(wù)器
public class UdpClientDemo {
public static void main(String[] args) throws Exception {
// 1. 發(fā)送數(shù)據(jù)包需要一個(gè)Socket
DatagramSocket socket = new DatagramSocket();
// 1.2 建立一個(gè)包
String msg = "你好";
InetAddress localhost = InetAddress.getByName("localhost");
System.out.println(localhost);
int port = 8080;
/*
通過(guò)UDP發(fā)送消息,需要通過(guò) 包 來(lái)發(fā)送,--> DatagramPacket(),該方法有多種重載形式,以下使用參數(shù)列表最多的那個(gè)
參數(shù):
- 要發(fā)送的 消息 的字節(jié)數(shù)組
- 從字節(jié)數(shù)組的哪個(gè)位置開始發(fā)送
- 發(fā)送的長(zhǎng)度
- 對(duì)方的 IP地址
- 對(duì)方的端口號(hào)
*/
DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
// 2. 發(fā)送數(shù)據(jù)包
socket.send(packet);
socket.close();
}
}
1.2、接收方
// 接收端,接收端需要保證存在,否則接收不到,所以需要提前開啟
public class UdpServerDemo {
public static void main(String[] args) throws Exception {
// 1. 接收也需要一個(gè)Socket,并且要開啟接收的端口
DatagramSocket socket = new DatagramSocket(8080);
// 需要一個(gè)字節(jié)數(shù)組來(lái)接收數(shù)據(jù)
byte[] buffer = new byte[1024];
// 1.2 封裝數(shù)據(jù)包
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
// 2. 接收數(shù)據(jù),阻塞式接收:一直處于監(jiān)聽狀態(tài)
socket.receive(packet);
// 關(guān)閉套接字
socket.close();
// 輸出一下
System.out.println(packet.getAddress().getHostAddress());
// trim():為了去除多余的空格
System.out.println(new String(packet.getData()).trim());
}
}
2、多次發(fā)送,多次接收
一方多次發(fā)送,一方多次接收,加上一個(gè) while(true) {} 死循環(huán),并規(guī)定在什么情況下退出即可。
2.1、發(fā)送方
public class ChatSenderDemo {
public static void main(String[] args) throws Exception {
// 使用Socket來(lái)接收
DatagramSocket socket = new DatagramSocket();
while (true) {
// 準(zhǔn)備發(fā)送包裹,從鍵盤接收數(shù)據(jù)
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
// 讀取一行
String data = reader.readLine();
byte[] dataBytes = data.getBytes();
DatagramPacket packet = new DatagramPacket(dataBytes, dataBytes.length, new InetSocketAddress("127.0.0.1", 6666));
// 發(fā)送
socket.send(packet);
// 什么時(shí)候退出
if ("bye".equals(data)) {
break;
}
}
// 關(guān)閉
socket.close();
}
}
2.2、接收方
public class ChatReceiveDemo {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(6666);
while (true) {
// 準(zhǔn)備接收數(shù)據(jù)包裹
byte[] buffer = new byte[1024];
// 用來(lái)接收數(shù)據(jù)
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
// 接收包裹,阻塞時(shí)接收
socket.receive(packet);
// 接收到的數(shù)據(jù)
String receiveData = new String(packet.getData()).trim();
// 打印到控制臺(tái)
System.out.println(receiveData);
// 什么時(shí)候退出
if ("bye".equals(receiveData)) {
break;
}
}
// 關(guān)閉
socket.close();
}
}
3、模擬雙方通信
模擬雙方使用UDP通信,需要開啟兩個(gè)線程,并對(duì)以上代碼進(jìn)行【共性提取】,進(jìn)一步進(jìn)行抽象。
由此,雙方可以通過(guò)指定的端口來(lái)互相發(fā)送消息。
3.1、發(fā)送方的線程
// 開啟多線程需要實(shí)現(xiàn) Runnable 接口,實(shí)現(xiàn) run()方法
public class TalkSender implements Runnable {
// 網(wǎng)絡(luò)套接字,發(fā)送需要
DatagramSocket socket = null;
// 緩沖讀取流
BufferedReader reader = null;
// 開啟哪個(gè)端口接收
private int fromPort;
// 對(duì)方的 IP
private String toIP;
// 對(duì)方的端口
private int toPort;
// 通過(guò)構(gòu)造方法進(jìn)行初始化
public TalkSender(int fromPort, String toIP, int toPort) {
this.fromPort = fromPort;
this.toIP = toIP;
this.toPort = toPort;
try {
socket = new DatagramSocket(fromPort);
} catch (SocketException e) {
e.printStackTrace();
}
}
// 重寫 run()方法,設(shè)置線程任務(wù)
@Override
public void run() {
while (true) {
String data = null;
try {
// 準(zhǔn)備發(fā)送包裹,從鍵盤接收數(shù)據(jù)
reader = new BufferedReader(new InputStreamReader(System.in));
// 讀取一行
data = reader.readLine();
byte[] dataBytes = data.getBytes();
DatagramPacket packet = new DatagramPacket(dataBytes, dataBytes.length, new InetSocketAddress(toIP, toPort));
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
// 什么時(shí)候退出
if ("bye".equals(data)) {
break;
}
}
// 關(guān)閉
socket.close();
}
}
3.2、接收方的線程
public class TalkReveicer implements Runnable {
DatagramSocket socket = null;
// 從哪個(gè)端口接收
private int formPort;
// 發(fā)送方是誰(shuí)
private String who;
public TalkReveicer(int formPort, String who) {
this.formPort = formPort;
this.who = who;
try {
socket = new DatagramSocket(formPort);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
String receiveData = null;
try {
// 準(zhǔn)備接收數(shù)據(jù)包裹
byte[] buffer = new byte[1024];
// 接收數(shù)據(jù)
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
// 接收數(shù)據(jù),阻塞式
socket.receive(packet);
// 接收到的數(shù)據(jù)
receiveData = new String(packet.getData());
System.out.println(who + ":" + receiveData.trim());
} catch (IOException e) {
e.printStackTrace();
}
// 什么時(shí)候退出
if ("bye".equals(receiveData)) {
break;
}
}
// 關(guān)閉
socket.close();
}
}
3.3、模擬學(xué)生
// 學(xué)生端
public class TalkStudent {
public static void main(String[] args) {
// 開啟 5555端口,發(fā)送到本機(jī)的 6666端口
new Thread(new TalkSender(5555, "localhost", 6666)).start();
// 規(guī)定使用 7777 端口接收老師發(fā)送的消息
new Thread(new TalkReveicer(7777, "老師")).start();
}
}
3.4、模擬老師
// 教師端
public class TalkTeacher {
public static void main(String[] args) {
// 開啟 8888端口,發(fā)送到本機(jī)的 7777端口
new Thread(new TalkSender(8888, "localhost", 7777)).start();
// 規(guī)定使用 6666 端口接收學(xué)生發(fā)送的消息
new Thread(new TalkReveicer(6666, "學(xué)生")).start();
}
}
總結(jié):
使用UDP通信,其實(shí)主要的步驟分為三步:
1 用 DatagramSocket() 來(lái)開啟端口,通過(guò)開啟端口聊天。
2 用DatagramPacket() 來(lái)發(fā)送或者接收數(shù)據(jù)。
3 關(guān)閉 DatagramSocket,釋放資源。
以上就是Java模擬UDP通信示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Java模擬UDP通信的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java模擬HTTP Get Post請(qǐng)求實(shí)現(xiàn)論壇自動(dòng)回帖功能
這篇文章主要介紹了Java模擬HTTP Get Post請(qǐng)求實(shí)現(xiàn)論壇自動(dòng)回帖功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09
java調(diào)用FFmpeg實(shí)現(xiàn)視屏壓縮功能的詳細(xì)步驟
這篇文章主要介紹了java調(diào)用FFmpeg實(shí)現(xiàn)視屏壓縮功能,本文簡(jiǎn)單的展示了java調(diào)用FFmpeg命令實(shí)現(xiàn)視屏的壓縮的詳細(xì)步驟,需要的朋友可以參考下2021-09-09
JVM性能調(diào)優(yōu)實(shí)現(xiàn)原理及配置
這篇文章主要介紹了JVM性能調(diào)優(yōu)實(shí)現(xiàn)原理及配置,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12
Spring Boot高級(jí)教程之使用Redis實(shí)現(xiàn)session共享
這篇文章主要為大家詳細(xì)介紹了Spring Boot高級(jí)教程之使用Redis實(shí)現(xiàn)session共享,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
springboot 異步調(diào)用的實(shí)現(xiàn)方法
這篇文章主要介紹了springboot 異步調(diào)用的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-04-04
使用jmx?exporter采集kafka指標(biāo)示例詳解
這篇文章主要為大家介紹了使用jmx?exporter采集kafka指標(biāo)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
springboot配置多數(shù)據(jù)源的實(shí)例(MongoDB主從)
下面小編就為大家分享一篇springboot配置多數(shù)據(jù)源的實(shí)例(MongoDB主從),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
java使用FFmpeg提取音頻的實(shí)現(xiàn)示例
在Java開發(fā)中,我們經(jīng)常會(huì)遇到需要使用FFmpeg來(lái)處理音視頻文件的情況,本文主要介紹了java使用FFmpeg提取音頻的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01

