新冠病毒的最新動(dòng)態(tài)廣州seo網(wǎng)站公司
歡迎瀏覽高耳機(jī)的博客
希望我們彼此都有更好的收獲
感謝三連支持!??
????????在網(wǎng)絡(luò)編程中,Echo Server 和 Echo Client 回顯是一種經(jīng)典的示例,用于演示基本的網(wǎng)絡(luò)通信。Echo Server 接收來(lái)自客戶端的數(shù)據(jù),并將相同的數(shù)據(jù)發(fā)送回客戶端。這種模式在測(cè)試網(wǎng)絡(luò)連接和理解網(wǎng)絡(luò)通信原理時(shí)非常有用。在這篇文章中,我們將使用 Java 語(yǔ)言來(lái)實(shí)現(xiàn)基于 UDP 協(xié)議的 Echo Server 和 Echo Client。?
目錄
UDP 協(xié)議概述
API介紹?
Echo Server 實(shí)現(xiàn)
服務(wù)器核心流程
服務(wù)器代碼詳解?
Echo Client 實(shí)現(xiàn)
客戶端核心流程
客戶端代碼詳解?
運(yùn)行演示?
?
UDP 協(xié)議概述
UDP(User Datagram Protocol)是一種無(wú)連接的網(wǎng)絡(luò)協(xié)議,它在 IP 協(xié)議的基礎(chǔ)上提供一種快速、簡(jiǎn)單的數(shù)據(jù)傳輸服務(wù)。與 TCP 協(xié)議不同,UDP 不建立連接,不保證數(shù)據(jù)的可靠傳輸,因此適用于對(duì)實(shí)時(shí)性要求高、可以容忍一定數(shù)據(jù)丟失的應(yīng)用場(chǎng)景,如視頻會(huì)議、在線游戲等。
API介紹?
DatagramSocket 是UDP Socket,用于發(fā)送和接收UDP數(shù)據(jù)報(bào)。?
構(gòu)造方法:
方法簽名 | 方法說(shuō)明 |
DatagramSocket() | 創(chuàng)建一個(gè)UDP數(shù)據(jù)報(bào)套接字的Socket,綁定到本機(jī)任意一個(gè)隨機(jī)端口(一般用于客戶端) |
DatagramSocket(int port) | 創(chuàng)建一個(gè)UDP數(shù)據(jù)報(bào)套接字的Socket,綁定到本機(jī)指定的端口(一般用于服務(wù)端)? |
方法:
方法簽名 | 方法說(shuō)明 |
void receive(DatagramPacket p) | 從此套接字接收數(shù)據(jù)報(bào)(如果沒(méi)有接收到數(shù)據(jù)報(bào),該方法會(huì)阻塞等待) |
void send(DatagramPacket p) | 從此套接字發(fā)送數(shù)據(jù)報(bào)包(不會(huì)阻塞等待,直接發(fā)送) |
void close() | 關(guān)閉此數(shù)據(jù)報(bào)套接字 |
?
DatagramPacket 是UDP Socket發(fā)送和接收的數(shù)據(jù)報(bào)。
構(gòu)造方法:
方法簽名 | 方法說(shuō)明 |
DatagramPacket(byte[] buf, int length) | 構(gòu)造一個(gè)DatagramPacket用來(lái)接收數(shù)據(jù)報(bào),接收的數(shù)據(jù)保存在字節(jié)數(shù)組(第一個(gè)參數(shù)buf)中,接收指定長(zhǎng)度(第二個(gè)參數(shù)length) |
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address) | 構(gòu)造一個(gè)DatagramPacket用來(lái)發(fā)送數(shù)據(jù)報(bào),發(fā)送的數(shù)據(jù)為字節(jié)數(shù)組(第一個(gè)參數(shù)buf)中,從offset到指定長(zhǎng)度(第二個(gè)參數(shù)length)。address指定目的主機(jī)的IP和端口號(hào) |
方法:
方法簽名 | 方法說(shuō)明 |
InetAddress getAddress() | 從接收的數(shù)據(jù)報(bào)中,獲取發(fā)送端主機(jī)IP地址;或從發(fā)送的數(shù)據(jù)報(bào)中,獲取接收端主機(jī)IP地址 |
int getPort() | 從接收的數(shù)據(jù)報(bào)中,獲取發(fā)送端主機(jī)的端口號(hào);或從發(fā)送的數(shù)據(jù)報(bào)中,獲取接收端主機(jī)端口號(hào) |
byte[] getData() | 獲取數(shù)據(jù)報(bào)中的數(shù)據(jù) |
構(gòu)造UDP發(fā)送的數(shù)據(jù)報(bào)時(shí),需要傳入SocketAddress,該對(duì)象可以使用InetSocketAddress來(lái)創(chuàng)建。
構(gòu)造方法:
方法簽名 | 方法說(shuō)明 |
InetSocketAddress(InetAddress addr, int port) | 創(chuàng)建一個(gè)Socket地址,包含IP地址和端口號(hào) |
Echo Server 實(shí)現(xiàn)
服務(wù)器核心流程
- 創(chuàng)建?
DatagramSocket
?并綁定到指定端口,開(kāi)始監(jiān)聽(tīng)客戶端的請(qǐng)求。 - 循環(huán)接收客戶端發(fā)送的數(shù)據(jù)。
- 將接收到的數(shù)據(jù)原樣發(fā)送回客戶端。
- 重復(fù)步驟 2 和 3,直到服務(wù)器關(guān)閉。
服務(wù)器代碼詳解?
package network;import javax.lang.model.element.NestingKind;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class UdpEchoServer {private DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}//通過(guò) start 啟動(dòng)服務(wù)器的核心流程public void start() throws IOException {System.out.println("服務(wù)器啟動(dòng)");while (true) {//此處不停的處理客戶端的請(qǐng)求//1.讀取客戶端的請(qǐng)求并解析DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);//阻塞并等待客戶端的請(qǐng)求。當(dāng)數(shù)據(jù)到達(dá)時(shí),它將數(shù)據(jù)存儲(chǔ)在?requestPacket?中。socket.receive(requestPacket);//將二進(jìn)制byte轉(zhuǎn)為字符串,方便輸出String request = new String(requestPacket.getData(),0, requestPacket.getLength());//2.根據(jù)請(qǐng)求計(jì)算響應(yīng),由于此處是回顯服務(wù)器,響應(yīng)就是請(qǐng)求.String response = process(request);//3.把響應(yīng)寫(xiě)回客戶端DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);//4.打印日志System.out.printf("[%s:%d] req=%s,resp=%s\n",requestPacket.getAddress(),requestPacket.getPort(),request,response);}}public String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer server = new UdpEchoServer(9090);server.start();}
}
Echo Client 實(shí)現(xiàn)
客戶端核心流程
- 創(chuàng)建?
DatagramSocket
。 - 從控制臺(tái)讀取用戶輸入。
- 將用戶輸入封裝成 UDP 數(shù)據(jù)包并發(fā)送到服務(wù)器。
- 接收服務(wù)器的響應(yīng)并打印到控制臺(tái)。
- 重復(fù)步驟 2-4,直到用戶選擇停止。
客戶端代碼詳解?
package network;import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null;private String serverIP;private int serverPort;// 構(gòu)造函數(shù),初始化socket并設(shè)置服務(wù)器的IP和端口public UdpEchoClient(String serverIP,int serverPort) throws SocketException {socket = new DatagramSocket();this.serverIP = serverIP;this.serverPort = serverPort;}public void start() throws IOException {System.out.println("啟動(dòng)客戶端");Scanner scanner = new Scanner(System.in);while (true) {//1.從控制臺(tái)讀取到用戶的輸入System.out.println("-> ");String request = scanner.next();//2.構(gòu)造出一個(gè) UPD 請(qǐng)求,發(fā)送給服務(wù)器// 將用戶輸入轉(zhuǎn)換為字節(jié)數(shù)組,并發(fā)送到服務(wù)器的指定IP和端口DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(this.serverIP),this.serverPort);socket.send(requestPacket);//3.從服務(wù)器讀取到響應(yīng)DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);//響應(yīng)轉(zhuǎn)換為字符串String response = new String(responsePacket.getData(),0,responsePacket.getLength());//4.把響應(yīng)打印到控制臺(tái)上System.out.println(response);}}public static void main(String[] args) throws IOException {//創(chuàng)建客戶端示例,綁定本地的9090端口UdpEchoClient client = new UdpEchoClient("127.0.0.1",9090);client.start();}
}
運(yùn)行演示?
1.依次啟動(dòng)server 和 client:
2.在client中輸入請(qǐng)求內(nèi)容,回車:
?綠色文本為輸入內(nèi)容,白色文本為server響應(yīng).
3.server打印請(qǐng)求和響應(yīng)日志:
????????實(shí)現(xiàn)一個(gè)基礎(chǔ)的 UDP Echo Server 和 Echo Client,理解 UDP 協(xié)議的工作原理和網(wǎng)絡(luò)通信的基本概念。這種模式不僅適用于學(xué)習(xí)目的,還可以作為構(gòu)建更復(fù)雜網(wǎng)絡(luò)應(yīng)用的基礎(chǔ)。?
希望這篇博客能為你理解網(wǎng)絡(luò)編程提供一些幫助
如有不足之處請(qǐng)多多指出
我是高耳機(jī)