UDP协议风格的客户端——服务器程序的特点就是通过数据包进行传输数据,也就是发送接收数据的时候,是以一个数据包为基本单位。
其中涉及的API有两个
- DatagramSocket,用于给服务器绑定端口号和ip来开启服务器。本质就是描述网卡文件的类。后续客户端就可以通过这两个来借助网络访问服务器
- DatagramPacket,这个类可以理解为就是一个数据包。
服务器端:
核心操作主要有两步
- 初始化操作,也就是实例化Datagramsocket对象,给服务器绑定端口号和ip号。
- 进入主循环:
a.读取数据并且解析
b.根据请求计算响应
c.把响应结果返回到客户端
示例代码:
public class UdpEchoServer {
//1.进行初始化操作
private DatagramSocket datagramSocket = null;
public UdpEchoServer(int port) throws SocketException {//指定端口号,ip号不指定的话就会默认关联到主机上的所有网卡ip
datagramSocket = new DatagramSocket(port);//此时这个服务器就绑定上了端口号和ip号。客户端就可以通过这两个来访问服务器
}
//2.进入主循环
public void start() throws IOException {
while(true){
//a.获取数据并且解析
DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);//创建数据包的时候需要带上缓冲区,来存放请求信息
datagramSocket.receive(requestPacket);//以传过去的数据包为基本单位接收数据。
//注:如果客户端没有发送数据过来服务器就会在这里阻塞。
System.out.println((requestPacket.getPort()));//如果客户端发送数据过来了,这个数据包里面应该会包含客户端的ip端口等信息。
System.out.println((requestPacket.getSocketAddress()));
String request = new String(requestPacket.getData(),0,requestPacket.getLength()).trim();
//从这个数据包里面获取请求信息。由于不一定会放满缓冲区,所以可以借助trim方法把数组空白区域去掉。
String respose = processRequest(request);//借助这个方法计算请求得到响应
//3.把响应返回到客户端
DatagramPacket resposePacket = new DatagramPacket(respose.getBytes(),respose.getBytes().length,requestPacket.getSocketAddress());
//需要重新构造一个数据包来传输响应,并且需要指定客户端的ip和端口号,可以借助客户端传过来的数据包获取
datagramSocket.send(resposePacket);//将这个数据包借助网卡发送出去。
}
}
private String processRequest(String request) {
return request;//由于是回显服务器,所以直接返回请求
}
public static void main(String[] args) throws IOException {
UdpEchoServer u = new UdpEchoServer(9988);
u.start();
}
}
服务器接收数据包并且处理写成死循环就是为了能够无时无刻的接收。
客户端:
主要分为四步
- 从用户这里读取数据
- 将数据构造成数据包发送给服务器
- 读取服务器发回的响应数据包
- 将响应打印出来
public class UdpEchoClient {
String Serverip;//服务器的ip
int ServerPort;//服务器的端口号
private DatagramSocket datagramSocket = null;
public UdpEchoClient(String serverip, int serverPort) throws SocketException {
Serverip = serverip;
ServerPort = serverPort;
datagramSocket = new DatagramSocket();//客户端不能指定端口号,因为同一个进程只能有一个端口号,如果指定
//了的话,打开多个客户端就会失败,应该由内核自己分配
}
public void start() throws IOException {
System.out.println("客户端启动");
while(true){
//1.从用户这里读取数据
Scanner s = new Scanner(System.in);
String request = s.nextLine();
//2.将请求构造成数据包发送到服务器
DatagramPacket reuestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(Serverip),ServerPort);
//在这个包里面需要指定服务器的ip和端口号
datagramSocket.send(reuestPacket);
//3.从服务器端读取响应
DatagramPacket resposePacket = new DatagramPacket(new byte[4096],4096);
datagramSocket.receive(resposePacket);//借助网卡读取到这个数据包里面
System.out.println((resposePacket.getSocketAddress()));
String respose = new String(resposePacket.getData(),0,resposePacket.getLength()).trim();
System.out.println((respose));//打印出这个响应
}
}
public static void main(String[] args) throws IOException {
UdpEchoClient u = new UdpEchoClient("127.0.0.1",9988);//根据前面设置的服务器的ip和端口号发送数据
u.start();
}
客户端通过访问服务器中自己设定的ip和端口号,就可以借助网络以DatagramPacket为基本单位来发送接受数据。这也是UDP协议风格的特点。