在線咨詢(本地)

線程一、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端口,顯示學生發來的消息
    }
}