什么是UDP?
UDP是User Datagram Protocol的简称,中文名是用户数据报协议,是OSI参考模型中的传输层协议,它是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。
和TCP编程相比,UDP编程就简单得多,因为UDP没有创建连接,数据包也是一次收发一个,所以没有流的概念。
如何使用UDP编程?
在Java中使用UDP编程,仍然需要使用Socket,因为应用程序在使用UDP时必须指定网络接口(IP地址)和端口号。注意:UDP端口和TCP端口虽然都使用0~65535,但他们是两套独立的端口,即一个应用程序用TCP协议占用了端口1234,不影响另一个应用程序用UDP协议占用端口1234。
案例要求
- 基于udp协议的服务器端和客户端用于实现简单的注册信息交互;
- 实现客户端向服务器的信息发送及服务器的信息反馈
案例实现
1.服务器端
//注册中心(服务器端)
public class RegisterCenter {
public static void main(String[] args) {
//基于udp协议的服务器端socket,监听8888端口
try (DatagramSocket socket = new DatagramSocket(8888)) {
//创建一个空的数据包,用于接收数据
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
// System.out.println(Arrays.toString(packet.getData()));
//接收客户端发送的数据包,(未发送时出处于阻塞状态)
socket.receive(packet);
// System.out.println(Arrays.toString(packet.getData()));
//发送的数据包是字节数组,所以用String的构造方法进行转换
System.out.println("客户端提交了新的注册信息:");
String name = new String(packet.getData(),packet.getOffset(),packet.getLength());
System.out.println("姓名:"+name);
socket.receive(packet);
String career = new String(packet.getData(),packet.getOffset(),packet.getLength());
System.out.println("职业:"+career);
socket.receive(packet);
String address = new String(packet.getData(),packet.getOffset(),packet.getLength());
System.out.println("来自:"+address);
//向客户端反馈信息
packet.setData("注册成功偶买噶,我终于注册成功了!".getBytes());
//发送数据包
socket.send(packet);
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.客户端
//注册客户端
public class RegisterClient {
public static void main(String[] args) throws IOException {
//基于udp协议的客户端socket
try (DatagramSocket socket = new DatagramSocket()) {
//设置进行“链接”的服务器地址和端口
socket.connect(InetAddress.getByName("192.168.0.120"),8888);
//创建新数据包
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
//设置数据包内容
packet.setData("亚索".getBytes());
//发送数据包
socket.send(packet);
packet.setData("战士".getBytes());
//发送数据包
socket.send(packet);
packet.setData("艾欧尼亚".getBytes());
//发送数据包
socket.send(packet);
//接受服务器数据
packet=new DatagramPacket(new byte[1024], 1024);
socket.receive(packet);
String message = new String(packet.getData(),packet.getOffset(),packet.getLength());
System.out.println("[服务器:]"+message);
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
客户端向服务器发送信息:
服务器向客户端的反馈信息:
注意事项
在客户端中接受服务器反馈信息时,也是用数据包的形式进行对信息的传输,
DatagramPackett类型的对象packet虽然指定了封装数据的字节数组和数据的大小,但在
客户端想用来接收反馈信息时,所能接收到的内容有效值却决于这个packet对象在最后一次设置内容时的有效长度,例如:在最后一次中向客户端发送“艾欧”,如果没有重新实例化packet对象,则就不能完整的接收到服务器的反馈信息:
所以在用客户端接收服务器反馈信息时,一定要对packet对象进行重新的实例化,以免对数据传输的丢失!
总结
- 使用UDP协议通信时,服务器和客户端双方无需建立连接;
- 服务器端用DatagramSocket(port)监听端口;
- 客户端使用DatagramSocket.connect()指定远程地址和端口;
- 双方通过receive()和send()读写数据;
- UDP协议的特点:无连接,不可靠,面向数据报。