Java实现的一个简单聊天软件

介绍

这是我自己学习Socket时写的,用到了多线程,Socket的知识,还有Java的IO技术,并且做了一个Java的UI,废话不多说,先上效果图
这里写图片描述

SendThread

这个类是用来实现数据的发送的,当按键按下时,会调用sendMessage方法

public class SendThread {

    ChatWindow chatWindow;
    private String remoteIP = "";
    private int port = 0;
    private String message = "";

    public SendThread(int port,ChatWindow window) {
        chatWindow = window;
    }

    public void notRun() {
        InetSocketAddress isa = new InetSocketAddress(remoteIP, port);
        try {
            Socket socket = new Socket();
            socket.connect(isa);
            OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream());
            writer.write(message);
            writer.flush();
            writer.close();
            System.out.println("将数据写入到流中");
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            message = "";
        }
    }

    public void senMessage(String host,int port,String message){
        remoteIP = host;
        this.port = port;
        this.message = message;
        notRun();
    }

}

ReceiveThread

这个类实现的功能是维护一个阻塞线程,来对端口进行监听,接受收到的信息,每当收到信息时,都会显示。

public class ReceiveThread extends Thread {

    private ServerSocket server;
    private ChatWindow window;

    public ReceiveThread(ChatWindow window) {
        this.window = window;
        try {
            server = new ServerSocket(0);
            window.setLocalPort(server.getLocalPort());
            start();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            window.printError("连接出错");
        }
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(true){
            Socket socket;
            try {
                socket = server.accept();
                InputStreamReader reader = new InputStreamReader(socket.getInputStream());
                int c;
                StringBuilder sb = new StringBuilder();
                while((c = reader.read()) != -1){
                    sb.append((char)c);
                }
                window.setReceive(sb.toString());
            } catch (IOException e) {
                // TODO Auto-generated catch block
                System.out.println("线程将接受到的数据写入对话框出错");
            }
        }
    }
}

ChatWindow

这个类是UI的实现,通过绑定各个按钮的操作来实现别的功能

public class ChatWindow extends JFrame {

    private JButton sendButton;
    private JButton cancelButton;
    private JButton receiveButton;
    private JTextArea receiveText;
    private JTextField sendText;

    private JLabel localPort;

    private JTextField remoteAddress;
    private JTextField remotePort;
    private SendThread sendThread;
    private ReceiveThread receiveThread;

    private void GUIini(){
        Container c = this.getContentPane();
        c.setLayout(new BorderLayout());
        setSize(400, 500);

        //第一个panel
        JPanel panel1 = new JPanel(new GridLayout(4, 2));
//      JPanel panel1 = new JPanel(new (4, 2));
        panel1.setSize(400, 75);
        panel1.add(new JLabel("当前机器的IP地址是:"));
        try {
            panel1.add(new JLabel(InetAddress.getLocalHost().getHostAddress()));
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            panel1.add(new JLabel("当前机器的IP地址是:" + "Unknown"));
        }
        panel1.add(new JLabel("当前对话的端口是:"));
        panel1.add(localPort = new JLabel(""+0));
        panel1.add(new JLabel("Remote Host IP Address:"));
        remoteAddress = new JTextField();
        remoteAddress.setColumns(0);
        panel1.add(remoteAddress);
        panel1.add(new JLabel("Remote Host Port:"));
        remotePort = new JTextField();
        remotePort.setColumns(0);
        panel1.add(remotePort);
        c.add(panel1,BorderLayout.NORTH);


        //第二个panel
        JPanel panel2 = new JPanel(new FlowLayout(FlowLayout.LEADING));
        panel2.setSize(400,200);
        panel2.add(new JLabel("收到的内容"));
        receiveText = new JTextArea(15,30);
        receiveText.setEditable(false);
        receiveText.setAutoscrolls(true);
        JScrollPane jsp = new JScrollPane(receiveText);
        panel2.add(jsp);
        //第三个panel
//      JPanel panel3 = new JPanel(new GridLayout(2, 1));
        panel2.add(new JLabel("请输入发送的内容"));
        sendText = new JTextField(30);
        sendText.setAutoscrolls(true);
        panel2.add(sendText);
        c.add(panel2,BorderLayout.CENTER);
        //c.add(panel3);
        //第四个panel
        JPanel panel4 = new JPanel(new GridLayout(1, 0));
        panel4.setSize(400,20);
        receiveButton = new JButton("开始接受数据");
        sendButton = new JButton("发送");
        cancelButton = new JButton("取消");
        panel4.add(receiveButton);
        panel4.add(cancelButton);
        panel4.add(sendButton);
        c.add(panel4,BorderLayout.SOUTH);
        //四个面板内容设置完毕

        setVisible(true);
        setResizable(false);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    private void ActionIni() {

        //键盘动作
        this.addKeyListener(new KeyListener() {

            @Override
            public void keyTyped(KeyEvent e) {

            }

            @Override
            public void keyReleased(KeyEvent e) {
                // TODO Auto-generated method stub
                if(e.getKeyCode() == KeyEvent.VK_ENTER){
                    //发送文本
                    sendThread.senMessage(remoteAddress.getText(), Integer.parseInt(remotePort.getText()), sendText.getText());
                    receiveText.setText(receiveText.getText() + "\n" + "发送:" + sendText.getText());
                }
            }

            @Override
            public void keyPressed(KeyEvent e) {
                // TODO Auto-generated method stub

            }
        });
        //取消按钮的动作
        cancelButton.addMouseListener(new MouseListener() {

            @Override
            public void mouseReleased(MouseEvent e) {
                // TODO Auto-generated method stub
                sendText.setText("");
            }

            @Override
            public void mousePressed(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseExited(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseEntered(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseClicked(MouseEvent e) {
                // TODO Auto-generated method stub

            }
        });
        sendButton.addMouseListener(new MouseListener() {

            @Override
            public void mouseReleased(MouseEvent e) {
                //发送文本
                sendThread.senMessage(remoteAddress.getText(), Integer.parseInt(remotePort.getText()), sendText.getText());
                receiveText.setText(receiveText.getText()  + "发送:" + sendText.getText()+ "\n");
            }

            @Override
            public void mousePressed(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseExited(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseEntered(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseClicked(MouseEvent e) {
                // TODO Auto-generated method stub

            }
        });
    }

    private void ThreadIni() {
        // TODO Auto-generated method stub
        sendThread = new SendThread(0, this);
        receiveThread = new ReceiveThread(this);
    }
    //构造函数
    public ChatWindow() {
        GUIini();
        ActionIni();
        ThreadIni();
    }

    public void printError(String err){
        System.out.println("Error occur:" + err);
    }

    //回调函数,用于接受从线程中返回的数据
    public void setReceive(String receive){
        receiveText.setText(receiveText.getText() + "收到:" + receive+ "\n" );
    }

    //当接受数据的线程开始工作以后,就调用该回调函数,设置当前聊天窗口使用的端口是哪个
    public void setLocalPort(int localPortText){
        localPort.setText(""+localPortText);
    }

    //放远,这个是整个程序的起点
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new ChatWindow();
    }

}

如何使用

将工程导入到Eclipse中以后,运行两次,因为这个程序不属于单例模式,所以可以出现两个窗口,在远程端口,远程地址那个输入框中分别输入另一个窗口中显示的IP和端口号,接下来在输入框中输入要发送的文字就可以了

源码下载

  • 28
    点赞
  • 158
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值