【java】模拟微信聊天(网络编程)

模拟微信聊天(网络编程)

在如今,微信聊天已经人们生活中必不可少的重要组成部分,人们的交流很多都是通过微信来进行的。本案例要求将多线程与 UDP 通信相关知识结合,模拟实现局域网内两位微信好友聊天小程序。

程序总体要求如下:程序启动时,让用户输入自己的微信号和好友的微信号,程序创建两个线程(发消息线程和接收消息线程),启动局域网聊天系统。

特别提示:
1、为了实现局域网内通信,用户发消息时,是通过广播(群发)功能实现的。发消息时将目标 IP 地址设置为 127.0.0.255。(当然,也可直接用对方的 IP 地址。)

2、微信号实际上是用作接收数据的端口号。例如,张三的微信号 5001,李四的微信号是 5008。那么张三在 5001 号端口进行监听和接收消息,而李四则在 5008 号端口进行监听和接收消息的。当张三给李四发消息时,实际上是向广播地址的 5008 端口号发送数据包。类似地,当李四向张三发送消息时,实际上是向广播地址的 5001 端口号发送数据包。

3、为了方便调试程序,我们希望能在同一台机子中同时启动两个程序,这时需要在 IDE 中执行同一程序两次,启动两个程序的运行实例。

【任务目标】

 学会分析“模拟微信聊天”任务的实现思路。
 根据思路独立完成“模拟微信聊天”任务的源代码编写、编译及运行。

 掌握网络通信中 UDP 协议的编程原理。

 掌握 UDP 网络通信 DatagramPacket 和 DatagramSocket 的使用。

【实现思路】

本程序涉及到多线程,可以采用基于接口的多线程实现技术。

1、 编写发送消息的线程类 SendTask,该类的主要功能时在其 run 方法中,创建套接字对象和数据包对象,获取键盘输入的文字,然后将其发送到 127.0.0.255 地址的好友端口号。

2、 编写接收消息的线程类 ReceiveTask,该类的主要功能时在其 run 方法中,创建套接字对象和数据包对象,在指定端口号监听(接收)消息,并将其打印出来。

编写主类 Room,在主方法中获取用户微信号和好友的微信号,分别创建与启动发送线程和接收线程。

特别注意:由于在 main 方法中要将用户微信号(端口号,演示程序中是 5001)传递给发送线程对象。因此,我们可以给 SendTask 类中添加一个 int 型成员属性 sendPort,增加一个有参数的构造方法,在 main 方法中创建该对象时将其进行初始化。类似的,给在 ReceiveTask 类中添加一个 int 型成员属性 receivePort,要将好友微信号(端口号,演示程序中是 5008)传递给接收线程对象。

【实现代码】
1、 SendTask 类

package cn.edu.gpnu.bank.cn.edu.gpnu.exp13;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class SendTask implements Runnable {
    
    
    private int sendPort; // 发消息的微信号(端口号)

    public SendTask(int sendPort) {
    
    
        this.sendPort = sendPort;
    }
    @Override
    public void run() {
    
    
        try {
    
    
            // 1. 创建 DatagramSocket 对象 ds
            DatagramSocket ds=new DatagramSocket();
            InetAddress inetAddress = InetAddress.getByName("127.0.0.255");
            Scanner sc = new Scanner(System.in);
            while (true) {
    
    
                // 2. 获取键盘输入的信息
                String str=sc.nextLine();
                // 3. 将消息转换为字节数组,再将其封装到 DatagramPacket 对象 dp 中
                byte[] arr=str.getBytes();
                DatagramPacket dp=new DatagramPacket(arr,arr.length,inetAddress,sendPort);
                // 4.ds 发送数据 dp
                ds.send(dp);
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

}

2、 ReceiveTask 类

package cn.edu.gpnu.bank.cn.edu.gpnu.exp13;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class ReceiveTask implements Runnable{
    
    
    private int receivePort;// 接收数据的端口号

    public ReceiveTask(int receivePort) {
    
    
        this.receivePort = receivePort;
    }

    //补充构造方法
    @Override
    public void run() {
    
    
        try {
    
    
            // 1.DatagramSocket 对象 ds
            DatagramSocket ds=new DatagramSocket(receivePort);
            // 2.创建字节数组和 DatagramPacket 对象 dp
            byte [] buf=new byte[1024];
            DatagramPacket dp=new DatagramPacket(buf,buf.length);
            //补充代码
            while (true) {
    
    
                // 3.ds 接收数据 sp
                ds.receive(dp);
                // 4.接收到的数据转化为字符串,并打印显示
                String str = "【"+dp.getAddress().getHostAddress()+"】:"+new String(dp.getData(),0, dp.getLength());
                System.out.println(str);
            }

        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }
}

3、 Room 类

package cn.edu.gpnu.bank.cn.edu.gpnu.exp13;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class Room {
    
    
    public static void main(String[] args) {
    
    
        //显示欢迎信息,获取用户微信号和好友微信号。
        System.out.println("欢迎进入模拟微信系统!");
        //补充代码
        //创建发送消息线程对象(传递用户微信号)并启动。
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入您的微信号(端口号):");
        int sendPort=sc.nextInt();
        SendTask s=new SendTask(sendPort);
        //补充代码
        //创建接收消息线程对象(传递好友微信号)并启动。
        System.out.println("请输入您的好友微信号(端口号):");

        int receivePort=sc.nextInt();
        ReceiveTask r=new ReceiveTask(receivePort);
        //补充代码
        System.out.println("微信聊天室已启动!");
        new Thread(s).start();
        new Thread(r).start();
    }

}

【运行结果】
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_52703008/article/details/126324839