目录
前言:
1.UDP协议API
1.1UDP编程原理
1.2DatagramSocket类
(1)DatagramSocket构造方法
(2)DatagramSocket普通方法
1.3DatagramPacket类
(1)DatagramPacket构造方法
(2)DatagramPacket普通方法
1.4InetSocketAddress类
2.代码案例
2.1服务器端
2.2客户端
2.3运行结果
前言:
在网络编程-002节中已经介绍了有关传输层UDP协议的基本知识,本节不再介绍有关UDP协议的基础内容,主要讲UDP协议的重点API及其使用方法,通过案例的形式完善。
序列:网络编程 - 003
1.UDP协议API
1.1UDP编程原理
对于UDP协议来说,具有无连接,面向数据报的特征,即每次都是没有建立连接,并且一次发送全部数据报,一次接收全部的数据报。
Java中使用UDP协议通信,主要基于DatagramSocket类来发送或接收数据报套接字,并使用DatagramPacket作为创建的UDP数据报,DatagramPacket类对象就是UDP协议中Socket的数据报。
1.2DatagramSocket类
DatagramSocket是UDP Socket,用于发送和接收UDP数据报。
(1)DatagramSocket构造方法
构造方法如下:
构造方法 | 方法说明 |
DatagramSocket() | 创建一个UDP数据报套接字的Socket,绑定到本机一个随机端口(一般用于客户端) |
DatagramSocket(int port) | 创建一个UDP数据报套接字的Socket,绑定到本机指定的端口(一般用于服务端) |
(2)DatagramSocket普通方法
普通方法如下:
方法 | 方法说明 |
void receive(DatagramPacket p) | 从此套接字接收数据报(如果没有接收到数据报,该方法会阻塞等待) |
void send(DatagramPacket p) | 从此套接字发送数据报包(不会阻塞等待,直接发送) |
void close() | 关闭此数据报套接字 |
1.3DatagramPacket类
(1)DatagramPacket构造方法
构造方法如下:
构造方法 | 方法说明 |
DatagramPacket(byte[] buf , int length) | 构造一个DatagramPacket以用来接收数据报,接收的数据保存在字节数组(第一个参数buf)中,接收指定长度(第二个参数length) |
DatagramPacket(byte[] buf , int offset , int length , SocketAddress address) | 构造一个DatagramPacket以用来发送数据报,发送的数据为字节数组(第一个参数buf)中,从offset到指定长度(第三个参数length)。address指定目的主机的IP和端口号 |
其中buf数组为输出型参数,offset默认为零,可以省略。
(2)DatagramPacket普通方法
普通方法如下:
方法 | 方法说明 |
InetAddress getAddress() | 从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址 |
int getPort() | 从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获取接收端主机端口号 |
byte[] getData() | 获取数据报中的数据 |
1.4InetSocketAddress类
构造UDP发送的数据报时,需要传入SocketAddress,该对象可以使用InetsocketAddress来创建。
InetSocketAddress(SocketAddress 的子类)构造方法:
方法 | 方法说明 |
InetSocketAddress(InetAddress addr , int port) | 创建一个Socket地址,包含IP地址和端口号 |
2.代码案例
利用传输层的UDP协议,我们可以实现一个实例。在Idea控制台手动输入字符串内容,从客户端发送给服务器端,然后服务器端不做任何处理,直接再次返回给客户端同样的字符串。
2.1服务器端
代码如下:
public class EchoServer {//服务器端
//1、创建一个DatagramSocket对象
DatagramSocket socket = null;
public EchoServer(int port) throws SocketException {//服务器端需要自己指定端口号
socket = new DatagramSocket(port);//这么写就是手动指定端口号
//socket = new DatagramSocket();//这么写就是系统自动分配端口号
}
public void start() throws IOException {
System.out.println("服务器启动...");
while (true){
DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
//requestPacket这个对象是用来承载数据的,在创建的时候需要创建一块内存空间来保存数据
socket.receive(requestPacket);
//当前完成的receive之后,数据是以二进制的形式存储到DatagramPacket中
//还需要把这个二进制的数据转化成字符串的形式
String request = new String(requestPacket.getData(),0,requestPacket.getLength());
//范围为0到requestPacket.getLength(),requestPacket.getLength()表示数据的真实长度
//2、根据请求,计算响应(服务器端最核心的作用)
String response = process(request);
//3、把响应写回到客户端
//搞一个响应对象,DatagramPacket
//把DatagramPacket构造刚才的数据,再通过send返回
DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),
0,
response.getBytes().length,
requestPacket.getSocketAddress());//指定数据内容,同时指定数据要发给谁
socket.send(responsePacket);
//4、打印一个日志,把这次的数据交互的详情给打印出来
System.out.printf("[%s:%d] req = %s,resp = %s\n",
responsePacket.getAddress().toString(),
responsePacket.getPort(),
request,
response);
}
}
public String process(String request) {//请求是啥样,响应就是啥样
//回转响应的方法
return request;
}
public static void main(String[] args) throws IOException {
EchoServer server = new EchoServer(9090);//实例测试
server.start();
}
}
2.2客户端
代码如下:
public class EchoClient {//客户端
private DatagramSocket socket = null;
private String serverIP = "";
private int serverPort = 0;
public EchoClient(String ip,int port) throws SocketException {
//创建这个对象不能手动指定端口
socket = new DatagramSocket();
//由于 UDP自身不会持有对端信息,就需要在应用程序里,把对端的情况给记录下来
//这里咱们主要记录对端的ip和端口
serverIP = ip;
serverPort = port;
}
public void start() throws IOException {
System.out.println("客户端启动...");
Scanner scanner = new Scanner(System.in);
while (true){
//1、控制台读取数据,作为请求
System.out.println(" -> ");
String request = scanner.next();
//2、把请求的内容构造成DatagramSocket对象,发送给服务器
DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),
request.getBytes().length,
InetAddress.getByName(serverIP),
serverPort);
socket.send(requestPacket);
//3、尝试获取服务器响应
DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
socket.receive(responsePacket);
//4、把响应给转换出字符串,并显示出来
String response = new String(responsePacket.getData(),
0,
responsePacket.getLength());
System.out.println(response);
}
}
public static void main(String[] args) throws IOException {
EchoClient client = new EchoClient("127.0.0.1",9090);
client.start();
}
}
2.3运行结果
在同时运行服务器端和客户端两段代码后,在客户端的控制台输入字符串,结果如图所示:
客户端:
服务器端:
以上便是对传输层的UDP协议API介绍,并举例说明了UDP协议的具体用法。