java实现多人在线聊天室
先放效果图:
登陆:
/**在本类109行附近调用了ChatClient类 * */ import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.Toolkit; import java.io.File; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPasswordField; import javax.swing.JTextField; import javax.swing.border.Border; import javax.swing.border.EtchedBorder; import javax.swing.border.TitledBorder; public class ClientLogin extends JFrame { private JTextField nametext ; private JPasswordField passwordtetx ; //private Object bPanel; public ClientLogin() { this.init() ; //init方法初始化 this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(true); } public void init() { this.setTitle("呆萌聊天室登陆"); this.setSize(330,230); //借用成熟美观尺寸 int y = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight() ; int x = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth() ; /**以上的方法要是不借助Eclipse实在是很难记住,尼玛! * */ this.setLocation( (x-this.getWidth() )/2, ( y-this.getHeight() )/2 ); this.setResizable(false); //不允许用户自行更改大小 Icon icon = new ImageIcon("d:"+File.separator+"login.jpg") ; JLabel label = new JLabel(icon) ; //设置登陆界面上边框 this.add(label,BorderLayout.NORTH) ; JPanel mainPanel = new JPanel() ; Border border = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED) ; mainPanel.setBorder(BorderFactory.createTitledBorder(border,"输入登陆信息",TitledBorder.CENTER,TitledBorder.TOP)) ; this.add(mainPanel,BorderLayout.CENTER) ; //将主面板加入frame mainPanel.setLayout(null) ; JLabel namelabel = new JLabel("请输入昵称") ; namelabel.setBounds(30,30,80,22) ; mainPanel.add(namelabel) ; nametext = new JTextField() ; nametext.setBounds(115,30,120,22); mainPanel.add(nametext) ; JLabel passwordlabel = new JLabel("请输入密码") ; passwordlabel.setBounds(30,60,80,22); mainPanel.add(passwordlabel) ; passwordtetx = new JPasswordField() ; passwordtetx.setBounds(115,60,120,22) ; mainPanel.add(passwordtetx) ; //接下来按钮位置排放 JPanel bPanel = new JPanel() ; bPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)) ; this.add(bPanel,BorderLayout.SOUTH) ; JButton reset = new JButton("重置") ; reset.addActionListener(new ActionListener() { //为“重置”按钮添加事件监听 public void actionPerformed(ActionEvent e) { nametext.setText(""); passwordtetx.setText(""); } }); bPanel.add(reset) ; /**下面开始实现提交按钮 * */ JButton submit = new JButton("登陆") ; submit.addActionListener(new LoginAction(this) ); //因为登陆相对复杂,重新为登陆写一个类 bPanel.add(submit) ; } /**下面开始写登陆类 * */ class LoginAction implements ActionListener { private JFrame self ; public LoginAction(JFrame self) { this.self = self ; } public void actionPerformed(ActionEvent e) { //System.out.println("用户名是:"+nametext.getText()+" 密码是:"+new String(passwordtext.getPassword())) ; try { //开始连接到服务器 Socket socket = new Socket("127.0.0.1",8888) ; new ChatClient(socket,nametext.getText()) ; //调用dispose方法关闭登陆框 self.dispose(); }catch(UnknownHostException e1) { e1.printStackTrace(); JOptionPane.showConfirmDialog(self, "找不到指定服务器!~","连接失败",JOptionPane.OK_OPTION,JOptionPane.ERROR_MESSAGE) ; }catch(IOException e1) { e1.printStackTrace() ; JOptionPane.showConfirmDialog(self, "连接服务器出错,请重试!","连接失败",JOptionPane.OK_OPTION,JOptionPane.ERROR_MESSAGE) ; } } } public static void main(String args[]) { new ClientLogin() ; } }
客户端:
import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import java.util.Date; import java.text.SimpleDateFormat; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextArea; public class ChatClient extends JFrame { private Socket socket ; //负责和服务器通信 private JTextArea sendArea ; //消息编辑区域 private JTextArea contentArea ; //群聊消息显示框 private String name ; //当前用户名称 public ChatClient(Socket socket,String name) { this.socket = socket ; this.name = name ; this.init() ; //初始化聊天客户端 this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(true); /*接下来启动单独线程,专门从服务器中读取数据 * */ ClientThread thread = new ClientThread(socket,contentArea) ; thread.start(); } public void init( ) { this.setTitle("我的聊天室"); this.setSize(300,400); int x = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth() ; int y = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight() ; this.setLocation( (x-this.getWidth() )/2, ( y-this.getHeight() )/2 ); this.setResizable(false); //不允许用户改变大小 contentArea = new JTextArea() ; contentArea.setLineWrap(true); //换行方法 JScrollPane logPanel = new JScrollPane(contentArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ) ; sendArea = new JTextArea() ; sendArea.setLineWrap(true); //控制每行显示长度最大不超过界面长度 JScrollPane sendPanel = new JScrollPane(sendArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ) ; //创建一个分隔窗格 JSplitPane splitpane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,logPanel,sendPanel) ; splitpane.setDividerLocation(250); this.add(splitpane,BorderLayout.CENTER) ; //按钮面板 JPanel bPanel = new JPanel() ; bPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)) ; this.add(bPanel,BorderLayout.SOUTH) ; JLabel namelabel = new JLabel("昵称: "+this.name+" ") ; bPanel.add(namelabel) ; JButton closeButton = new JButton("关闭") ; closeButton.addActionListener( new ActionListener( ) { public void actionPerformed(ActionEvent e) { } }); bPanel.add(closeButton) ; JButton sendButton = new JButton("发送") ; sendButton.addActionListener(new ActionListener() { //@Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub String str = sendArea.getText() ; SimpleDateFormat formater = new SimpleDateFormat("HH:mm:ss") ; String time = formater.format(new Date() ) ; String sendStr = name+" "+time+" 说: "+str ; PrintWriter out = null ; try { out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream() ) ) ; out.println(sendStr) ; out.flush(); }catch(Exception e1) { e1.printStackTrace(); } sendArea.setText(""); } }); bPanel.add(sendButton) ; } } //客户端与服务器端通信的线程类 class ClientThread extends Thread { private Socket socket ; private JTextArea contentArea ; public ClientThread(Socket socket, JTextArea conteArea) { this.socket = socket ; this.contentArea = conteArea ; } public void run() { BufferedReader br = null ; try { br = new BufferedReader(new InputStreamReader( socket.getInputStream())) ; String str = null ; while( (str = br.readLine()) != null) { System.out.println(str) ; contentArea.append(str); contentArea.append("\n"); } } catch(IOException e) { e.printStackTrace(); } finally { if(br != null) { try { br.close () ; }catch(IOException e) { e.printStackTrace(); } } } }}
服务器端:
import java.util.List; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; public class ChatServer { private List<Socket> sockets = new ArrayList<Socket>() ; //类集的应用 public ChatServer() throws IOException { ServerSocket ss = new ServerSocket(8888) ; System.out.println("服务器已在监听8888端口") ; while(true) { Socket socket = ss.accept() ; sockets.add(socket) ; String ip = socket.getInetAddress().getHostAddress() ; System.out.println("新用户进入!ip是"+ip) ; Thread thread = new Thread(new ServerRunner(sockets,socket)) ; thread.start(); } } public static void main(String args[]) { try { new ChatServer() ; } catch(Exception e) { e.printStackTrace(); } } } class ServerRunner implements Runnable { private List<Socket> sockets ; private Socket currentSocket ; //当前socket public ServerRunner (List<Socket> sockets,Socket currentSocket) { this.sockets = sockets ; this.currentSocket = currentSocket ; } public void run() { String ip = currentSocket.getInetAddress().getHostAddress() ; BufferedReader br = null ; try { br = new BufferedReader(new InputStreamReader(currentSocket.getInputStream())) ; String str = null ; while((str = br.readLine()) != null) { System.out.println(ip+"说"+str) ; //往所有的客户端写入信息 for(Socket temp : sockets) { PrintWriter pw = new PrintWriter(new OutputStreamWriter(temp.getOutputStream())) ; pw.println(str) ; pw.flush(); } } }catch(IOException e) { e.printStackTrace(); } } }