在线咨询(本地)

线程一、TalkSend()

package XiaoShuai; // 包名,属于XiaoShuai这个包

import java.io.BufferedReader; // 导入缓冲读取器,用于读取输入
import java.io.IOException; // 导入IO异常处理
import java.io.InputStreamReader; // 导入输入流读取器
import java.net.DatagramPacket; // 导入UDP数据包类
import java.net.DatagramSocket; // 导入UDP套接字类
import java.net.InetSocketAddress; // 导入IP地址和端口类
import java.net.SocketException; // 导入套接字异常类

public class TalkSend implements Runnable { // 定义一个可以被线程运行的发送类

    DatagramSocket socket = null; // 声明UDP套接字
    BufferedReader reader = null; // 声明输入读取器

    private int fromPort; // 发送消息的端口
    private String toIP; // 接收方IP
    private int toPort; // 接收方端口

    public TalkSend(int fromPort, String toIP,int toPort) { // 构造器,初始化端口和IP
        this.fromPort = fromPort; // 保存发送端口
        this.toPort = toPort; // 保存接收端口
        this.toIP = toIP; // 保存接收端IP

        try {
            socket = new DatagramSocket(fromPort); // 创建UDP套接字并绑定发送端口
            reader = new BufferedReader(new InputStreamReader(System.in)); // 初始化键盘输入读取器
        } catch (SocketException e) { // 捕获套接字异常
            throw new RuntimeException(e); // 抛出运行时异常
        }
    }

    @Override
    public void run() { // 实现线程run方法
        while (true) { // 无限循环,持续发送消息
            try {
                String data = reader.readLine(); // 从键盘读取一行输入
                byte[] datas = data.getBytes(); // 将字符串信息转为字节数组
                DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(this.toIP, this.toPort)); // 创建UDP数据包,指定目标地址和端口

                socket.send(packet); // 发送UDP数据包
                if (data.equals("bye")) { // 如果输入为"bye"
                    break; // 退出循环,结束发送
                }
            } catch (IOException e) { // 捕获IO异常
                throw new RuntimeException(e); // 抛出运行时异常
            }
        }
        socket.close(); // 关闭UDP套接字,释放资源
    }
}

线程二、TalkReceive()

package XiaoShuai; // 包名,属于XiaoShuai这个包

import java.io.IOException; // 导入IO异常处理
import java.net.DatagramPacket; // 导入UDP数据包类
import java.net.DatagramSocket; // 导入UDP套接字类
import java.net.SocketException; // 导入套接字异常类

public class TalkReceive implements Runnable{ // 定义一个可以被线程运行的接收类
    DatagramSocket socket = null; // 声明UDP套接字
    private int port; // 接收消息的端口
    private String msgFrom; // 发消息的人名(显示用)

    public TalkReceive(int port,String msgFrom) { // 构造器,初始化端口和名称
        this.port = port; // 保存端口
        this.msgFrom = msgFrom; // 保存发送者名字
        try {
            socket = new DatagramSocket(port); // 创建UDP套接字并绑定接收端口
        } catch (SocketException e) { // 捕获套接字异常
            throw new RuntimeException(e); // 抛出运行时异常
        }
    }

    @Override
    public void run() { // 实现线程run方法
        while(true){ // 无限循环,持续接收消息
            //准备接受包裹
            try {
                byte[] container = new byte[1024]; // 创建字节数组容器,用于存放接收数据
                DatagramPacket packet = new DatagramPacket(container,0,container.length); // 创建UDP数据包,指定容器
                socket.receive(packet);//阻塞式接收包裹

                //断开连接 bye
                byte[] data = packet.getData(); // 获取包裹里的数据
                String receiveData = new String(data,0,data.length); // 将字节数据转换为字符串
                System.out.println(msgFrom +":" + receiveData); // 打印发送者名字和内容

                if(receiveData.equals("bye")){ // 如果内容为“bye”
                    break; // 退出循环,结束接收
                }
            } catch (IOException e) { // 捕获IO异常
                throw new RuntimeException(e); // 抛出运行时异常
            }
        }
        socket.close(); // 关闭UDP套接字,释放资源
    }
}

学生聊天主类

package XiaoShuai; // 包名,属于XiaoShuai这个包

public class TalkStudent { // 学生聊天主类
    public static void main(String[] args) { // 主方法,程序入口
        new Thread(new TalkSend(7777,"localhost",9999)).start(); // 启动发送线程:本地7777端口发消息到9999端口
        new Thread(new TalkReceive(8888,"老师")).start(); // 启动接收线程:监听8888端口,显示老师发来的消息
    }
}

老师聊天主类

package XiaoShuai; // 包名,属于XiaoShuai这个包

public class TalkTeacher { // 老师聊天主类
    public static void main(String[] args) { // 主方法,程序入口
        new Thread(new TalkSend(5555,"localhost",8888)).start(); // 启动发送线程:本地5555端口发消息到8888端口
        new Thread(new TalkReceive(9999,"学生")).start(); // 启动接收线程:监听9999端口,显示学生发来的消息
    }
}