JavaGUI之UDP网络聊天室实现

package internet_coding;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author swordsmanye
 * @data 2019/8/30 15:36
 */
public class GUIChart extends Frame {
    /**
     * desc: GUI聊天
     *
     * @param
     */
    private TextField tf;
    private Button send;
    private Button log;
    private Button clear;
    private Button shake;
    private TextArea viewText;
    private TextArea sendText;
    private DatagramSocket socket;
    private BufferedWriter bw;


    public static void main(String[] args) {
        new GUIChart();
    }

    public GUIChart() {
        // 初始化界面位置和大小
        init();
        // 配置最底下的panel
        southPanel();
        // 配置中间的panel
        centerPanel();
        // 事件响应
        event();
    }

    private void init() {
        this.setLocation(600, 200);
        this.setSize(500, 600);
        this.setBackground(Color.WHITE);
        // 初始化的时候开启socket,避免每次发送数据都要创建socket对象,浪费内存
        try {
            socket = new DatagramSocket();
            // 创建记录文件 。需要在尾部追加
            bw = new BufferedWriter(new FileWriter("config.txt", true));
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 开启接收线程
        new Received().start();
        this.setVisible(true);
    }

    private void southPanel() {
        Panel south = new Panel();
        // 创建文本字段存储IP地址
        tf = new TextField(15);
        tf.setText("10.90.139.97");
        tf.setBackground(Color.WHITE);
        send = new Button("send");
        log = new Button("log");
        clear = new Button("clear");
        shake = new Button("shake");
        south.add(tf);
        south.add(send);
        south.add(log);
        south.add(clear);
        south.add(shake);
        this.add(south, BorderLayout.SOUTH);
    }

    private void centerPanel() {
        Panel center = new Panel();
        // 显示文本区域
        viewText = new TextArea();
        // 显示文本区域无法编辑
        viewText.setEditable(false);
        // 设置背景颜色为白色
        viewText.setBackground(Color.WHITE);
        viewText.setFont(new Font("xxx", Font.PLAIN, 15));

        // 发送文本区域
        sendText = new TextArea(5, 1);
        sendText.setBackground(Color.WHITE);
        sendText.setFont(new Font("xxx", Font.PLAIN, 15));
        // 设置为边界布局管理器 (Frame默认为流式布局)
        center.setLayout(new BorderLayout());
        // 发送的文本局域放在南边
        center.add(sendText, BorderLayout.SOUTH);
        // 显示的区域放在中间
        center.add(viewText, BorderLayout.CENTER);
        this.add(center, BorderLayout.CENTER);

    }

    private void event() {
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {

                try {
                    socket.close();
                    bw.close();
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
                System.exit(0);
            }
        });

        // 发送事件监听
        send.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                send();
            }
        });

        // 记录事件监听
        log.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                logFile();
            }
        });

        // 清屏事件监听
        clear.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                viewText.setText("");
            }
        });

        // 震动事件监听
        shake.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
//                shake();
                send(new byte[]{-1}, tf.getText());
            }
        });

        // 开启键盘监听
        sendText.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                // 需要加Ctrl + enter的话,可以添加 && e.isControlDown()
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    send();
                }
            }
        });
    }



    /**
     * 获取当前时间
     *
     * @return
     */
    public String getCurrentTime() {
        // 创建当前日期对象
        Date d = new Date();
        // 将时间格式化形式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM年dd日 HH:mm:ss");
        // 将时间格式化
        return sdf.format(d);
    }

    /**
     * 获取到窗口位置,然后修改即可
     */
    private void shake() {
        int x = this.getLocation().x;
        int y = this.getLocation().y;

        // 修改位置
        try {
            this.setLocation(x + 20, y + 20);
            Thread.sleep(20);
            this.setLocation(x + 20, y - 20);
            Thread.sleep(20);
            this.setLocation(x - 20, y + 20);
            Thread.sleep(20);
            this.setLocation(x - 20, y - 20);
            Thread.sleep(20);
            this.setLocation(x, y);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 一初始化就需要有这个类似于数据库的文件
     */
    private void logFile() {
        try {
            bw.flush();
            FileInputStream fis = new FileInputStream("config.txt");
            // 在内存中创建缓冲区
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            int len;
            byte[] arr = new byte[1024 * 4];
            while ((len = fis.read(arr)) != -1) {
                baos.write(arr, 0, len);
            }
            // 将内存中的内容转成字符串
            String str = baos.toString();
            viewText.setText(str);

            fis.close();

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


    private void send(byte[] arr, String ip) {
        try {
            DatagramPacket packet =
                    new DatagramPacket(arr, arr.length, InetAddress.getByName(ip), 9999);
            // 发送数据
            socket.send(packet);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 绑定发送事件方法
     */
    private void send() {
        // 获取发送区域的内容
        String message = sendText.getText();
        // 获取IP地址
        String ip = tf.getText();
        ip = ip.trim().length() == 0 ? "255.255.255.255" : ip;
        // 随机端口号
        try {
            send(message.getBytes(), ip);
            String time = getCurrentTime();
            String str = time + "\r\n我对 " + (ip.equals("255.255.255.255") ? "所有人" : ip) + " 说: \r\n" + message + "\r\n\r\n";
            // 将信息添加到显示区域
            viewText.append(str);
            // 将信息写入到数据库中(config.txt)
            bw.write(str);
            // 清空发送区域消息
            sendText.setText("");

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

    }


    /**
     * 接收端程序
     * 接收和发送需要同时执行,所以定义成多线程的。
     */
    private class Received extends Thread {
        @Override
        public void run() {
            try {
                // 创建socket 相当于码头
                socket = new DatagramSocket(9999);
                // 创建packet 相当于集装箱
                DatagramPacket packet = new DatagramPacket(new byte[1024 * 4], 1024 * 4);
                while (true) {
                    // 接收信息
                    socket.receive(packet);
                    // 接收字节数据
                    byte[] arr = packet.getData();
                    // 获取有效的字节数据
                    int len = packet.getLength();
                    // 如果发过来的数组第一个存储的值为-1,并且数组长度为1
                    if (arr[0] == -1 && len == 1) {
                        shake();
                        // 终止本次循环,继续下次循环,因为震动后不需要执行下面的代码
                        continue;
                    }
                    // 数据转成字符串
                    String message = new String(arr, 0, len);
                    // 获取当前时间
                    String time = getCurrentTime();
                    // 获取IP地址
                    String ip = packet.getAddress().getHostAddress();
                    String str = time + "\r\n" + ip + "对我说:\r\n" + message + "\r\n\r\n";
                    // 显示到显示区域
                    viewText.append(str);
                    // 将数据写入到数据库中
                    bw.write(str);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


}

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值