javaGUI多人聊天功能
段茜琳 人气:0服务器
package com.ff.chat.chatserver.frame; import javax.swing.*; import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; import java.io.IOException; import java.net.BindException; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.Iterator; public class ServerFrame extends JFrame { JTextArea msgArea; ArrayList<Socket> socketArrayList = new ArrayList<>(); boolean serverFlag = true;//服务器启动标志 StringBuffer sb = new StringBuffer(); ServerSocket serverSocket; //创建服务器端的显示窗口 public void creatFrame(){ this.setTitle("聊天室-服务器端"); this.setSize(500,500); this.setLocationRelativeTo(null); this.setResizable(false); this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); //创建一个面板 JPanel jp = new JPanel(new BorderLayout()); //中间面板 JPanel centerPanel = new JPanel(); msgArea = new JTextArea(30,40); msgArea.setEditable(false); JScrollPane jsp = new JScrollPane(msgArea); centerPanel.add(jsp); jp.add(centerPanel); this.add(jp); this.setVisible(true); this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { int res = JOptionPane.showConfirmDialog(null,"确定要关闭服务器吗?", "操作提示",JOptionPane.OK_CANCEL_OPTION); if(res == 0){ try { dispose(); serverSocket.close(); } catch (IOException ioException) { ioException.printStackTrace(); } } } }); } //启动服务器,创建ServerSocket public void startServer(){ try { //创建ServerSocket serverSocket = new ServerSocket(9998); System.out.println("等待客户端连接"); //循环监听客户端连接 while (serverFlag){ if(serverSocket.isClosed()){ serverFlag = false; break; } Socket socket = serverSocket.accept(); System.out.println("客户端连接成功"); socketArrayList.add(socket); //为每一个客户端开启一个线程,监听客户端发来的消息 new ServerThread(socket).start(); } } catch (BindException b) { b.printStackTrace(); System.out.println("服务器端口被占用"); System.exit(0); } catch (IOException e) { e.printStackTrace(); System.out.println("服务器启动失败"); serverFlag = false; } } //创建一个内部类,开启一个线程,接收消息 class ServerThread extends Thread{ Socket socket; DataInputStream in; DataOutputStream out; boolean clientFlag = true; public ServerThread(Socket socket){ this.socket = socket; try { this.in = new DataInputStream(socket.getInputStream()); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { //监听接收客户端发送的消息 while (clientFlag){ if(socket.isClosed()){ break; } try { String msg = in.readUTF();//读到客户端发送的消息 sb.append(msg+"\n"); System.out.println(sb); msgArea.setText(sb.toString()); //从服务器端向客户端发送消息 if(socketArrayList.size() > 0){ Iterator<Socket> it = socketArrayList.iterator(); while (it.hasNext()){ Socket soc = it.next(); if(soc.isClosed()){//当客户端某个socket已经为关闭状态,移除此socket it.remove(); continue; } //客户端socket如果没有关闭,向客户端发送消息 out = new DataOutputStream(soc.getOutputStream()); out.writeUTF(sb.toString()); out.flush(); } } } catch (EOFException ef){ System.out.println("ip为:"+socket.getInetAddress()+"的客户端下线了"); clientFlag = false; }catch (IOException e) { e.printStackTrace(); } } } } }
package com.ff.chat.chatserver.frame; public class ServerRun { public static void main(String[] args) { ServerFrame serverFrame = new ServerFrame(); serverFrame.creatFrame(); serverFrame.startServer(); } }
客户端
注意:要在自己的电脑上运行多次客户端需要勾选如下选项
1.登录界面
package com.ff.chat.chatclient.frame; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.Socket; public class LoginFrame extends JFrame { JTextField accountField = null; //创建窗口 public void creatFrame(){ this.setTitle("聊天窗口"); this.setSize(400,400); this.setResizable(false); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setLocationRelativeTo(null); /* * 创建一个4行1列的面板 * */ JPanel jp = new JPanel(new GridLayout(4,1)); //欢迎登陆面板 JPanel welcomePanel = new JPanel(); JLabel welcomLabel = new JLabel("欢迎登陆"); welcomePanel.add(welcomLabel); //账号面板 JPanel accountPanel = new JPanel(); JLabel accountLabel = new JLabel("账号"); accountField = new JTextField(15); accountPanel.add(accountLabel); accountPanel.add(accountField); //密码面板 JPanel passwordPanel = new JPanel(); JLabel passwordLabel = new JLabel("密码"); JPasswordField passwordField = new JPasswordField(15); passwordPanel.add(passwordLabel); passwordPanel.add(passwordField); //登录按钮面板 JPanel btnPanel = new JPanel(); JButton loginBtn = new JButton("登录"); JButton regBtn = new JButton("注册"); btnPanel.add(loginBtn); btnPanel.add(regBtn); jp.add(welcomePanel); jp.add(accountPanel); jp.add(passwordPanel); jp.add(btnPanel); this.add(jp); this.setVisible(true); //组件绑定事件监听 loginBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { //获得账号密码 String account = accountField.getText(); String password = new String(passwordField.getPassword()); if(account.length() == 0){ JOptionPane.showMessageDialog(null,"账号不能为空", "操作提示",JOptionPane.WARNING_MESSAGE); return; } if(password.length() == 0){ JOptionPane.showMessageDialog(null,"密码不能为空", "操作提示",JOptionPane.WARNING_MESSAGE); return; } //预留2.0版本 与数据库交互 //连接服务器,创建Socket对象 try { Socket socket = new Socket("192.168.31.179",9998);//该地址为要连接的服务器的地址 new ClientFrame(socket,account).creatFrame(); dispose(); //释放当前登录窗口 } catch (IOException ioException) { ioException.printStackTrace(); JOptionPane.showMessageDialog(null,"服务器连接失败", "操作提示",JOptionPane.WARNING_MESSAGE); } } }); } }
2.聊天界面
package com.ff.chat.chatclient.frame; import com.ff.chat.chatclient.utils.DateUtil; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.util.Date; public class ClientFrame extends JFrame { String account; Socket socket; DataOutputStream out;//数据输出字节流 DataInputStream in;//数据输入字节流 JTextArea msgArea; //创建聊天窗口时,初始化数据 public ClientFrame(Socket socket,String account){ this.socket = socket; this.account = account; try { out = new DataOutputStream(socket.getOutputStream()); in = new DataInputStream(socket.getInputStream()); } catch (IOException e) { e.printStackTrace(); } } //创建聊天窗口 public void creatFrame(){ this.setTitle("聊天窗口-"+account); this.setSize(500,500); this.setResizable(false); this.setLocationRelativeTo(null); this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); //创建一个面板 JPanel jp = new JPanel(new BorderLayout()); //中间面板 JPanel centerPanel = new JPanel(); msgArea = new JTextArea(30,40); msgArea.setEditable(false);//不可以直接编辑 JScrollPane jsp = new JScrollPane(msgArea); centerPanel.add(jsp); //底部面板 JPanel bottomPanel = new JPanel(); JTextField msg = new JTextField(30); JButton sendBtn = new JButton("发送"); bottomPanel.add(msg); bottomPanel.add(sendBtn); jp.add(centerPanel); jp.add(bottomPanel,BorderLayout.SOUTH); this.add(jp); this.setVisible(true); //发送按钮添加监听事件 sendBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String m = msg.getText(); //获得客户端输入的聊天内容 if(m.length() == 0){ JOptionPane.showMessageDialog(null,"不能发送空白消息"); return; } //向服务器发送消息 try { String ms = account+":"+DateUtil.dateStr(new Date())+"\n"+m; out.writeUTF(ms);//向服务器发送消息 out.flush(); msg.setText("");//发送成功,清空聊天文本框 } catch (IOException ioException) { ioException.printStackTrace(); JOptionPane.showMessageDialog(null,"服务器连接失败"); } } }); //聊天窗口添加事件监听 this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { int res = JOptionPane.showConfirmDialog(null,"你确定要退出吗?", "操作提示",JOptionPane.OK_CANCEL_OPTION); if(res == 0){ dispose(); new LoginFrame().creatFrame(); } try { socket.close(); } catch (IOException ioException) { ioException.printStackTrace(); } } }); //启动一个线程,监听服务器是否向客户端发送了消息 new ClientThread(socket).start(); } //创建一个内部类 class ClientThread extends Thread{ //接收从服务器发来的消息 Socket socket; boolean serverFlag = true; public ClientThread(Socket socket){ this.socket = socket; } @Override public void run(){ //监听接收服务器发来的消息 while (serverFlag){ try { String ms = in.readUTF(); msgArea.setText(ms); } catch (IOException e) { System.out.println("客户端"+account+"下线了"); serverFlag = false; } } } } }
3.运行客户端
package com.ff.chat.chatclient.frame; public class ClientRun { public static void main(String[] args) { new LoginFrame().creatFrame(); } }
加载全部内容