Java 网络编程 --基于UDP实现一对一聊天功能

UDP 基本流程:

UDP发送端基本流程:
1、使用DatagramSocket 指定端口 创建发送端
2、准备数据 一定转成字节数组
3、 封装成DatagramPacket 包裹,需要指定目的地
4、发送包裹send​(DatagramPacket p) *
5、释放资源

UDP接收端基本流程:
1、使用DatagramSocket 指定端口 创建接收端
2、准备容器 封装成DatagramPacket 包裹
3、阻塞式接收包裹receive​(DatagramPacket p)
4、分析数据 getData​() getLength​()
5、释放资源
实现聊天功能显然需要发送端和接收端,并且需要不断循环接收发送。

简化版实现:

我们先实现一个简化版:
发送端:

public class UdpTalkClient {
	public static void main(String[] args) throws Exception {
		System.out.println("发送方启动中。。。。");
		// 1、使用DatagramSocket 指定端口,创建发送端
		DatagramSocket client = new DatagramSocket(8888);
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		while (true) {
			// 2、准备数据 一定转成字节数组
			String data = br.readLine();
			byte[] datas = data.getBytes();
			// 3、封装成DatagramPacket 包裹,需要指定地址
			DatagramPacket packet = new DatagramPacket(datas, 0, datas.length,
					new InetSocketAddress("localhost", 9999));
			// 4、发送包裹
			client.send(packet);
			if(data.equals("bye")) {
				break;
			}
		}
		// 5、释放资源
		client.close();
	}
}

接收方:

public class UdpTalkServer {
	public static void main(String[] args) throws Exception {
		System.out.println("接收方启动中。。。");
		// 1、使用DatagramSocket 指定端口创建接收端
		DatagramSocket server = new DatagramSocket(9999);
		while (true) {
			// 2、准备容器封装成DatagramPacket 包裹
			byte[] container = new byte[1024 * 60];
			DatagramPacket packet = new DatagramPacket(container, container.length);
			// 3、阻塞式接收包裹
			server.receive(packet);
			// 4、分析数据
			byte[] datas = packet.getData();
			String msg = new String(datas, 0, packet.getLength());
			System.out.println(msg);
			if(msg.equals("bye")) {
				break;
			}
		}
		// 5、释放资源
		server.close();
	}
}

运行以上两个代码效果基本是这样:
在这里插入图片描述
目前的代码只能单方发送接收。这显然不是我们要的效果,为了实现双方都能接收和发送,我们加入多线程。

封装:

接下来只要拷贝简化版代码利用面向对象封装了
发送方线程封装:

public class TalkSend implements Runnable {
	private DatagramSocket client;// 发送端
	BufferedReader br; // 输入流
	private String toIp;// 发送目标ip
	private int toPort;// 发送目标端口 和接收端使用端口一致
	public TalkSend(int port, String toIp, int toPort) {
		this.toIp = toIp;
		this.toPort = toPort;
		try {
			client = new DatagramSocket(port);
			br = new BufferedReader(new InputStreamReader(System.in));
		} catch (SocketException e) {
			e.printStackTrace();
		}
	}
	@Override
	public void run() {
		while (true) {
			try {
				// 2、准备数据 一定转成字节数组
				String data = br.readLine();
				byte[] datas = data.getBytes();
				// 3、封装成DatagramPacket 包裹,需要指定地址
				DatagramPacket packet = new DatagramPacket(datas, 0, datas.length,
						new InetSocketAddress(this.toIp, this.toPort));
				// 4、发送包裹
				client.send(packet);
				if(data.equals("bye")) {
					break;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		// 5、释放资源
		client.close();
	}
}

接收方线程封装:

public class TalkReceive implements Runnable {
	private DatagramSocket server; // 接收端
	private int port; // 接收端使用端口
	private String from; // 发送方标记
	public TalkReceive(int port, String from) {
		this.from = from;
		try {
			server = new DatagramSocket(port);
		} catch (SocketException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void run() {
		while (true) {
			try {
				// 2、准备容器封装成DatagramPacket 包裹
				byte[] container = new byte[1024 * 60];
				DatagramPacket packet = new DatagramPacket(container, container.length);
				// 3、阻塞式接收包裹
				server.receive(packet);
				// 4、分析数据
				byte[] datas = packet.getData();
				String msg = new String(datas, 0, packet.getLength());
				System.out.println(from + ":" + msg);
				if(msg.equals("bye")) {
					break;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		// 5、释放资源
		server.close();
	}
}

模拟淘宝客户和老板对话启动多线程:
客户:

public class TalkCustomer {
	public static void main(String[] args) {
		new Thread(new TalkSend(9999, "localhost", 8888)).start();
		new Thread(new TalkReceive(7777, "老板")).start();
	}
}

老板:

public class TalkService {
	public static void main(String[] args) {
		new Thread(new TalkReceive(8888, "客户")).start();
		new Thread(new TalkSend(6666, "localhost", 7777)).start();
	}
}

运行测试:
在这里插入图片描述
效果实现了。

重视基础,才能走的更远。
原文地址:https://www.cnblogs.com/xzlf/p/12681519.html