UDP协议是一种不可靠的网络协议,它在通信实例的两端个建立一个Socket,但这两个Socket之间没有虚拟链路,这两个Socket只是发送、接收数据报的对象。Java提供了DatagramSocket对象作为基于UDP协议的Socket,使用DatagramPacket代表DatagramSocket发送、接收数据报。
可以认为UDP协议的Socket类似于码头,数据报则类似于集装箱;码头的作用就是负责发送、接收集装箱,而DatagramSocket的作用则是发送、就收数据报。因此对于通信双方而言,没有所谓的客户端和服务器端的概念。因为UDP协议是面向非连接的协议,没有建立连接过程,因此它的通信效率很好;但可靠性就不如TCP协议。
使用DatagramSocket发送、接收数据
DatagramSocket的构造器:
- DatagramSocket():创建一个DatagramSocket实例,绑定在本机默认IP地址、本机所有可用端口中随机选择某个端口。
- DatagramSocket(int port):绑定到本机默认IP地址,指定端口。
- DatagramSocket(int port,InetAddress laddr):指定IP地址和端口。
接收和发送数据的方法: - receive(DatagramPocket p):从该DatagramSocket中接收数据报。
- send(DatagramPocket p):以该DatagramSocket对象向外发送数据报。
我们还需要DatagramPocket决定数据报的目的地: - DatagramPocket(byte[] buf,int length):以一个空的byte数组创建DatagramPocket对象,该对象是用于接收DatagramSocket中的数据。
- DatagramPocket(byte[] buf,int length,InetAddress addr,int port):包含数据的数组,并指定IP地址和端口来决定数据报的目的地。
- DatagramPocket(byte[] buf,int offset,int length):数据从offset开始,最多存放length个字节。
- DatagramPocket(byte[] buf,int offset,int length,InetAddress addr,int port):指定数据,IP地址和端口。
代码:
server端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.Scanner;
public class UDPServer {
private DatagramSocket socket; //实现UDP编码的工具包
private DatagramPacket packet; //封装数据报的类
private Scanner scanner;
private final int port = 5676;
public UDPServer() {
try {
socket = new DatagramSocket(port); //server 进程和该端口号绑定
byte[] bytes = new byte[1024];
packet = new DatagramPacket(bytes, 0, bytes.length);
scanner = new Scanner(System.in);
} catch (SocketException e) {
e.printStackTrace();
}
}
public void startSever() { //服务器启动之后的业务逻辑
//(1)接收用户的请求
try {
while(true) {
socket.receive(packet); //接收用户请求的
//处理收到的数据
String str = new String(packet.getData(), 0, packet.getLength());
System.out.println("接收到客户端发送的数据为: " + str);
//根据收到的信息做出对应的逻辑处理
//然后将处理之后的结果返回给用户
System.out.println("请输入你向客户端回复信息 : ");
String s = scanner.nextLine();
byte[] bytes = s.getBytes();
//数据如何知道应该发给谁呢
//获取到 发出请求的用户的信息
DatagramPacket sendpacket = new DatagramPacket(bytes, 0, bytes.length,
packet.getAddress(), packet.getPort());
// client 对应的ip 和port packet.getAddress(), packet.getPort()
socket.send(sendpacket);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
socket.close();
}
}
public static void main(String[] args) {
new UDPServer().startSever();
}
}
client端:
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
public class UDPClient {
private final String IP = "127.0.0.1"; //代词
private final int port = 5676;
private DatagramSocket socket; //实现UDP编码的工具包
private DatagramPacket packet; //封装数据报的类
private Scanner scanner;
public UDPClient() {
try {
socket = new DatagramSocket(); //server 进程和该端口号绑定
byte[] bytes = new byte[1024];
packet = new DatagramPacket(bytes, 0, bytes.length);
scanner = new Scanner(System.in);
} catch (SocketException e) {
e.printStackTrace();
}
}
public void startClient() { //客户端启动之后的业务逻辑
try {
while(true) {
System.out.println("请输入你的请求 : ");
String s = scanner.nextLine();
byte[] bytes1 = s.getBytes();
//数据如何知道应该发给谁呢
//获取到 发出请求的用户的信息
DatagramPacket sendpacket = new DatagramPacket(bytes1, 0, bytes1.length,
InetAddress.getByName(IP), port);
socket.send(sendpacket);
if(s.equals("exit")){
break;
}
socket.receive(packet); //接收用户请求的
//处理收到的数据
String str = new String(packet.getData(), 0, packet.getLength());
System.out.println("接收到服务器回复的数据为: " + str);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
socket.close();
}
}
public static void main(String[] args) {
new UDPClient().startClient();
}
}
运行结果: