• 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();
    	}
    }
    
    

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

    重视基础,才能走的更远。
  • 相关阅读:
    统计 (Standard IO)
    存储过程中的错误处理
    簡單SQL存儲過程實例
    SQLSERVER存储过程基本语法
    SQL Server游标的使用【转】
    实现业务系统中的用户权限管理--实现篇
    实现业务系统中的用户权限管理--设计篇
    C#.net 微信公众账号接口开发
    jquery select radio
    asp.net Repeater使用例子,包括分页
  • 原文地址:https://www.cnblogs.com/xzlf/p/12681519.html
Copyright © 2020-2023  润新知