合工大Java路强实验三——简易聊天界面

直接上代码。

package Experiment3;

//尝试一下通过Java提供的UI,改变界面
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;

//在客户端的textarea添加scrollpane
//更改ui风格适应windows11
//客户端退出时在服务器端添加相应。
public class ClientChat {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
        ClientJframe clientJframe = new ClientJframe();
        clientJframe.init();
    }
}

class ClientJframe extends JFrame {
    //GUI布局
    //聊天记录显示区
    JLabel HeadLabel = new JLabel("聊天记录");
    private JButton say = new JButton("Send");
    private JButton exit = new JButton("Exit");
    private Box vbox = Box.createVerticalBox();
    private Box hbox = Box.createHorizontalBox();
    private Box hBox2 = Box.createHorizontalBox();
    private JTextArea ta = new JTextArea(200, 200);
    JScrollPane clientScrollPane = new JScrollPane(
                ta,
                ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
        );
    //聊天记录输入区
    private JTextField tf = new JTextField();

    //端口
    // 静态常量主机端口号
    private static final String CONNSTR = "127.0.0.1";
    // 静态常量服务器端口号
    private static final int CONNPORT = 8888;
    private Socket socket = null;

    //Client发送数据
    private DataOutputStream dataOutputStream = null;

    //客户端连接上服务器判断符号
    private boolean isConn = false;

    /**
     * 无参的构造方法 throws HeadlessException
     */
    public ClientJframe() throws HeadlessException {
        super();
    }

    public void init() throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
        this.setTitle("客户端窗口");
        hBox2.add(ta);
        hBox2.add(clientScrollPane);
        vbox.add(HeadLabel);
        vbox.add(hBox2);
        hbox.add(tf);
        hbox.add(say);
        hbox.add(exit);
        vbox.add(hbox);
        this.add(vbox);
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        this.setSize(400,400);

        // 添加监听,使回车键可以输入数据(判断数据合法性),
        // 并輸入到聊天框,换行
        tf.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                String strSend = tf.getText();
                if (strSend.trim().length() == 0) {
                    return;
                }
                //客户端信息strSend发送到服务器上
                send(strSend);
                tf.setText("");

            }
        });

        say.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                String strSend = tf.getText();
                if (strSend.trim().length() == 0) {
                    return;
                }
                //客户端信息strSend发送到服务器上
                send(strSend);
                tf.setText("");
            }
        });

        exit.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });

        //关闭事件
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ta.setEditable(false);
        tf.requestFocus();//光标聚焦在输入框上;

        try {
            socket = new Socket(CONNSTR, CONNPORT);
            isConn = true;
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 启动多线程
        new Thread(new Receive()).start();

        this.setVisible(true);
    }

    /**
     * 客户端发送信息到服务器上的方法
     */
    public void send(String str) {
        try {
            dataOutputStream = new DataOutputStream(socket.getOutputStream());
            dataOutputStream.writeUTF(str);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * 
     * @deprecated 多线程的类,实现了Runnable接口的类
     */
    class Receive implements Runnable {
        @Override
        public void run() {
            try {
                while (isConn) {
                    DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
                    String str = dataInputStream.readUTF();
                    //通讯消息
                    ta.append(str);
                }
            } catch (SocketException e) {
                System.out.println("Server stoped!!");
                ta.append("Server stoped!!");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
package Experiment3;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Iterator;


public class ServerChat {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) throws Exception {
        ServerJframe serverJframe = new ServerJframe();
        serverJframe.init();
    }
}

class ServerJframe extends JFrame {
    //GUI相关属性
    JTextArea serverTa = new JTextArea(200,200);
    JTextField serverTf = new JTextField();
    private JLabel serverHeadLabel = new JLabel("聊天记录");
    JButton startBtn = new JButton("启动");
    JButton stopBtn = new JButton("停止");
    JButton sendBtn = new JButton("发送");
    private Box vbox = Box.createVerticalBox();
    private Box hbox = Box.createHorizontalBox();
    private Box hBox2 = Box.createHorizontalBox();
    private JScrollPane scrollPane = new JScrollPane(serverTa);
    //端口
    private static final int PORT = 8888;
    //ServerSocket
    private ServerSocket serverSocket = null;
    private Socket socket = null;

    //Server接受数据
    private DataInputStream dataInputStream = null;

    // 多个客户端访问时,客户端对象存放入List中
    private ArrayList<ClientCoon> ccList = new ArrayList<ClientCoon>();

    // 服务器启动的标志 (其实ServerSocket ss 初始化出来时以为者服务器的启动)
    private boolean isStart = false;

    public void init() throws Exception {
        this.setTitle("服务器端窗口");
        this.setSize(400,400);
        hbox.add(serverTf);
        hbox.add(scrollPane);
        vbox.add(serverHeadLabel);
        vbox.add(hbox);
        hBox2.add(serverTf);
        hBox2.add(sendBtn);
        hBox2.add(stopBtn);
        hBox2.add(startBtn);
        vbox.add(hBox2);
        this.add(vbox);

        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

        

        this.setSize(400,400);

        //判断服务器是否已经开启  
        
        //按钮监听监听服务器开启,置开始位false
        startBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    if (serverSocket == null) {
                        serverSocket = new ServerSocket(PORT);
                    }
                    isStart = true;
                    //startServer();
                    serverTa.append("Server is in ready. \n");
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
        });
        // 终止按钮监听停止服务器,置开始位true
        stopBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    if (serverSocket != null) {
                        serverSocket.close();
                        isStart = false;
                    }
                    System.exit(0);
                    serverTa.append("Server has been quit Connection\n");
                    System.out.println("Server has been quit Connection\n");

                } catch (Exception e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        });

        sendBtn.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                String msg = serverTf.getText();
                if(msg.equals("")){
                    JOptionPane.showMessageDialog(null,"请输入信息!","Warnning",JOptionPane.WARNING_MESSAGE);
                }else{
                    serverTa.append("Server: "+msg+"\n");
                    serverTf.setText("");
                    Iterator<ClientCoon> iterator = ccList.iterator();
                    while(iterator.hasNext()){
                        ClientCoon cc = iterator.next();
                        cc.send(msg);
                    }
                }
            }
        });

        // this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // serverTa.setEditable(false);
        this.setVisible(true);

        startServer();
        if (isStart) {
            System.out.println("Started.\n");
        } else {
            JOptionPane.showMessageDialog(null,"Hasn't been started.","Error",JOptionPane.ERROR_MESSAGE);
        }
    }


    public void startServer() throws Exception {
        try {
            try {
                serverSocket = new ServerSocket(PORT);
                isStart = true;
            }catch (Exception e) {
                e.printStackTrace();
            }
            
            while (isStart) {
                socket = serverSocket.accept();
                ccList.add(new ClientCoon(socket));
                serverTa.append("\n" + "@" + socket.getInetAddress() + "/" + socket.getPort()+"Have been connected to the server");
            }
            
        } catch (SocketException e) {
            System.out.println("Stream has been closed");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    
    class ClientCoon implements Runnable {
        Socket socket = null;

        public ClientCoon(Socket socket) {
            this.socket = socket;
            (new Thread(this)).start();
        }

        //接受客户端信息(多线程run()方法)
        @Override
        public void run() {
            try {
                DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
                // 为了让服务器能够接受到每个客户端的多句话
                while (isStart) {
                    String str = dataInputStream.readUTF();
                    serverTa.append("\n@" + socket.getInetAddress() + "||" + socket.getPort() + ":" + str + "\n");
                    //服务器向每个客户端发送别的客户端发来的信息
                    // 遍历ccList,调用send方法,在客户端里接受应该是多线程的接受
                    String strSend = "\n" + socket.getInetAddress() + "||" + socket.getPort() + ":" + str + "\n";
                    Iterator<ClientCoon> iterator = ccList.iterator();
                    while (iterator.hasNext()) {
                        ClientCoon clientCoon = iterator.next();
                        clientCoon.send(strSend);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // 服务器向每個连接对象发送数据的方法
        public void send(String str) {
            try {
                DataOutputStream dataOutputStream = new DataOutputStream(this.socket.getOutputStream());
                dataOutputStream.writeUTF(str);
            } catch (SocketException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 运行结果如上图。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值