Java案例分析
【案例9-1】 模拟微信聊天
2024-10-25 10 0
简介 1.案例描述 在如今,微信聊天已经人们生活中必不可少的重要组成部分,人们的交流很多都是通过微信来进行的。本案例要求:将多线程与UDP通信相关知识结合,模拟实现微信聊天小程序。通过监听指定的端口号、目标IP地址和目标端口号,实现消息的发送和接收功能,并显示聊天的内容
【案例9-1】 模拟微信聊天
【案例介绍】
1.案例描述
在如今,微信聊天已经人们生活中必不可少的重要组成部分,人们的交流很多都是通过微信来进行的。本案例要求:将多线程与UDP通信相关知识结合,模拟实现微信聊天小程序。通过监听指定的端口号、目标IP地址和目标端口号,实现消息的发送和接收功能,并显示聊天的内容。
2.运行结果
运行结果
【案例目标】
l 学会分析“模拟微信聊天”任务的实现思路。
l 根据思路独立完成“模拟微信聊天”任务的源代码编写、编译及运行。
l 掌握网络通信中UDP协议的编程原理。
l 掌握UDP网络通信DatagramPacket和DatagramSocket的使用。
【案例分析】
(1)第一要知道用什么技术实现,通过上述任务描述可知此任务是使用多线程与UDP通信相关知识实现的。要实现图中的聊天窗口界面。首先需要定义一个实现微信聊天功能的类,类中需要定义访问微信聊天的输出语句,从而获取输入的发送端端口号、接收端端口号以及实现发送和接收功能的方法。
(2)实现发送数据的功能。该功能通过一个实现了Runnable接口的类实现,类中需要定义获取发送数据的端口号,并在实现run()的方法中,编写发送数据的方法。
(3)实现接收数据的功能。该功能通过一个实现了Runnable接口的类实现,类中需要定义获取接收数据的端口号,并在实现run()的方法中,编写显示接收到的数据的方法。
(4)创建完所有的类与方法后,运行两次程序,同时开启两个窗口来实现聊天功能。
【案例实现】
(1)创建微信聊天程序,开启两个聊天窗口,需要创建两个聊天程序。两个聊天程序代码分别如下所示。
Room.java
1 package chapter0901;
2 import java.util.Scanner;
3 public class Room {
4 public static void main(String[] args) {
5 System.out.println("微信聊天欢迎您!");
6 Scanner sc = new Scanner(System.in);
7 System.out.print("请输入您的微信号登录:");
8 int sendPort = sc.nextInt();
9 System.out.print("请输入您要发送消息的微信号:");
10 int receivePort = sc.nextInt();
11 System.out.println("微信聊天系统启动!!");
12 //发送操作
13 new Thread(new SendTask(sendPort), "发送端任务").start();
14 //接收操作
15 new Thread(new ReceiveTask(receivePort), "接收端任务").start();
16 }
17 }
上述代码中,第12行代码用多线程实现发送端口号以及实现发送端功能的方法。第14行代码用多线程实现接收端口号以及实现接收端功能的方法。
Lucy.java
1 package chapter0901;
2 import java.util.Scanner;
3 public class Lucy {
4 public static void main(String[] args) {
5 System.out.println("微信聊天欢迎您!");
6 Scanner sc = new Scanner(System.in);
7 System.out.print("请输入您的微信号登录:");
8 int sendPort = sc.nextInt();
9 System.out.print("请输入您要发送消息的微信号:");
10 int receivePort = sc.nextInt();
11 System.out.println("微信聊天系统启动!!");
12 //发送操作
13 new Thread(new SendTask(sendPort), "发送端任务").start();
14 //接收操作
15 new Thread(new ReceiveTask(receivePort), "接收端任务").start();
16 }
17 }
(2)创建发送数据的任务类,其代码如下所示。
SendTask.java
1 package chapter0901;
2 import java.net.DatagramPacket;
3 import java.net.DatagramSocket;
4 import java.net.InetAddress;
5 import java.util.Scanner;
6 public class SendTask implements Runnable {
7 private int sendPort; // 发数据的端口号
8 // 构造方法
9 public SendTask(int sendPort) {
10 this.sendPort = sendPort;
11 }
12 @Override
13 public void run() {
14 try {
15 // 1. 创建DatagramSocket对象
16 DatagramSocket ds = new DatagramSocket();
17 // 2.输入要发送的数据
18 Scanner sc = new Scanner(System.in);
19 while (true) {
20 String data = sc.nextLine();// 获取键盘输入的数据
21 // 3.封装数据到 DatagramPacket对象中
22 byte[] buf = data.getBytes();
23 DatagramPacket dp = new DatagramPacket(buf, buf.length,
24 InetAddress.getByName("127.0.0.255"),sendPort);
25 // 4.发送数据
26 ds.send(dp);
27 }
28 } catch (Exception e) {
29 e.printStackTrace();
30 }
31 }
32 }
上述代码中,第6~10行代码声明了一个名称为sendPort的变量表示发送数据的端口号,并通过该类的构造方法获取所输入的端口号。第12~29行代码,实现run()方法,在run()方法中,首先创建了DatagramSocket对象,然后通过Scanner对象和循环方法获取键盘输入的数据,并将获取的数据封装到了DatagramPacket对象中,最后通过DatagramSocket对象的send()方法发送数据。在循环方法中,由于发送数据时可能多次连续发送,所以将循环条件设置为true,表示不断循环获取和发送数据。在创建DatagramPacket对象时,为了让当前局域网的所有人都接收到消息,所以将IP地址设置为127.0.0.255。
(3)创建接收数据的任务类,其代码如下所示。
ReceiveTask.java
1 package chapter0901;
2 import java.net.DatagramPacket;
3 import java.net.DatagramSocket;
4 public class ReceiveTask implements Runnable{
5 private int receivePort;// 接收数据的端口号
6 public ReceiveTask(int receivePort) {
7 this.receivePort = receivePort;
8 }
9 @Override
10 public void run() {
11 try {
12 // 1.DatagramSocket对象
13 DatagramSocket ds = new DatagramSocket(receivePort);
14 // 2.创建DatagramPacket对象
15 byte[] buf = new byte[1024];
16 DatagramPacket dp = new DatagramPacket(buf, buf.length);
17 // 3.接收数据
18 while (true) {
19 ds.receive(dp);
20 // 4.显示接收到的数据
21 String str = new String(dp.getData(), 0,
22 dp.getLength());
23 System.out.println("收到" +
24 dp.getAddress().getHostAddress()
25 + "--发送的数据--" + str);
26 }
27 } catch (Exception e) {
28 e.printStackTrace();
29 }
30 }
31 }
上述代码中,第4行代码声明了一个名称为receivePort的变量来表示接收数据的端口号,第5~7行代码定义一个该类的构造方法,并通过该类的构造方法获取所输入的端口号,第9~28行代码在run()方法中,首先创建了DatagramSocket对象,创建该对象时需要传入接收数据的端口号,然后创建用于接收数据的DatagramPacket对象,接下来通过循环的方法来接收数据,最后通过输出语句来显示接收到的数据。