java socket简易聊天室
来源:互联网 发布:广州小孩学编程 编辑:程序博客网 时间:2024/05/08 08:38
对学完java socket的朋友有一定的帮助,因为当你学好这方面的知识后,想必也有做着玩玩的念头!如下:
项目图参照
User类
package hfz.addAction.cn;//用户信息类 public class User{ private String name; public User(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } /* public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; }*/}
注册块
package hfz.Register.cn;public class Register extends JFrame implements ActionListener{ JLabel labelName,labelName1; JLabel labelSex,labelSex1; JLabel labelPassword1,labelPassword11; JLabel labelPassword2,labelPassword22; ButtonGroup bg=new ButtonGroup(); //性别2个放一起选择 JTextField textName; JRadioButton radioBoy; JRadioButton radioGirl; JLabel logoimagePosition1=new JLabel(); JLabel logoimagePosition2=new JLabel(); JPasswordField textPassword1; JPasswordField textPassword2; JButton b1; JButton b2; JButton b3; JPanel Panel=new JPanel(); JLabel imagePos; public Register() { this.setTitle(" 用户注册"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(530,300); //窗口居中 Dimension us = this.getSize(); Dimension them = Toolkit.getDefaultToolkit().getScreenSize(); int X = (them.width - us.width) / 2 ; int Y = (them.height - us.height) / 2 ; this.setLocation(X,Y); getContentPane().add(Panel); Panel.setLayout(null); //设置框架窗口的布局管理器为null //添加组件 Font f = new Font("宋体",Font.PLAIN,12); labelName = new JLabel("用户名:"); labelName.setFont(f); labelName1 = new JLabel("(用户名长度限制为2-15字节)"); labelName1.setFont(f); labelSex = new JLabel("性 别:"); labelSex.setFont(f); labelSex1 = new JLabel("(请选择您的性别)"); labelSex1.setFont(f); labelPassword1 = new JLabel("口 令:"); labelPassword1.setFont(f); labelPassword11 = new JLabel("(密码不得少于6个字符多于12个字符)"); labelPassword11.setFont(f); labelPassword2 = new JLabel("口 令:"); labelPassword2.setFont(f); labelPassword22 = new JLabel("(请再输一遍确认)"); labelPassword22.setFont(f); radioBoy = new JRadioButton("男 生"); radioBoy.setBackground(new Color(150,205,155)); radioBoy.setSelected(true); bg.add(radioBoy); radioGirl = new JRadioButton("女 生"); radioGirl.setBackground(new Color(150,205,155)); bg.add(radioGirl); textName = new JTextField(10); textName.setToolTipText("☆请输入您要注册的用户名☆"); textPassword1 = new JPasswordField(10); textPassword1.setToolTipText("☆请输入您的密码☆"); textPassword2 = new JPasswordField(10); textPassword2.setToolTipText("☆请再次输入密码确认☆"); b1 = new JButton("提 交"); b1.setBackground(new Color(0,155,0)); b1.addActionListener(this); b2 = new JButton("重 置"); b2.setBackground(new Color(0,155,0)); b2.addActionListener(this); b3 = new JButton("返 回"); b3.setBackground(new Color(0,155,0)); b3.addActionListener(this); //背景 Icon image = new ImageIcon("image/2.jpg"); imagePos = new JLabel(image); //手工设置各个组件的位置和大小 labelName.setBounds(new Rectangle(40, 20, 60, 20)); textName.setBounds(new Rectangle(100, 20, 180, 20)); labelName1.setBounds(new Rectangle(300, 20, 200, 20)); labelSex.setBounds(new Rectangle(40, 55, 60, 20)); radioBoy.setBounds(new Rectangle(95, 55, 55, 20)); logoimagePosition1.setBounds(new Rectangle(150, 52, 30, 25)); radioGirl.setBounds(new Rectangle(185, 55, 55, 20)); logoimagePosition2.setBounds(new Rectangle(245, 52, 30, 25)); labelSex1.setBounds(new Rectangle(300, 54, 150, 25)); labelPassword1.setBounds(new Rectangle(40, 85, 60, 20)); textPassword1.setBounds(new Rectangle(100, 85, 180, 20)); labelPassword11.setBounds(new Rectangle(300, 85, 220, 20)); labelPassword2.setBounds(new Rectangle(40, 120, 60, 20)); textPassword2.setBounds(new Rectangle(100, 120, 180, 20)); labelPassword22.setBounds(new Rectangle(300, 120, 220, 20)); b1.setBounds(new Rectangle(60, 210, 80, 25)); b2.setBounds(new Rectangle(170,210, 80, 25)); b3.setBounds(new Rectangle(280, 210, 80, 25)); imagePos.setBounds(new Rectangle(0,0,530,300)); //添加组件到面板 Panel.add(labelName); Panel.add(textName); Panel.add(labelName1); Panel.add(labelSex); Panel.add(radioBoy); Panel.add(logoimagePosition1); Panel.add(radioGirl); Panel.add(logoimagePosition2); Panel.add(labelSex1); Panel.add(labelPassword1); Panel.add(textPassword1); Panel.add(labelPassword11); Panel.add(labelPassword2); Panel.add(textPassword2); Panel.add(labelPassword22); Panel.add(b1); Panel.add(b2); Panel.add(b3); Panel.add(imagePos); this.add(Panel); this.setResizable(false); this.setVisible(true); } @Override public void actionPerformed(ActionEvent e) { Object obj = e.getSource(); if(obj == b2){ //清空 textName.setText(""); textPassword1.setText(""); textPassword2.setText(""); } if(obj==b3){ //返回 new ClientLogin(); this.setVisible(false); } if (obj==b1) { Properties userPro=new Properties(); File file=new File("hfz.properties"); CatUtil.loadPro(userPro, file); String u_name=textName.getText(); String u_pwd=new String(textPassword1.getPassword()); String u_pwd_ag=new String( textPassword2.getPassword()); //判断是否存在 if (u_name.length()!=0) { if (userPro.containsKey(u_name)) { try { throw new Exception("用户名存在"); } catch (Exception e1) { e1.printStackTrace(); } }else{ try { isPassword(userPro, file, u_name, u_pwd, u_pwd_ag); } catch (Exception e1) { e1.printStackTrace(); } } }else { try { throw new Exception("用户名不能为空"); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } } private void isPassword(Properties userPro, File file, String u_name, String u_pwd, String u_pwd_ag) throws Exception { if (u_pwd.equals(u_pwd_ag)) { if (u_pwd.length() != 0) { userPro.setProperty(u_name, u_pwd_ag); try { userPro.store(new FileOutputStream(file), "Copyright (c) Boxcode Studio"); } catch (FileNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } b1.setEnabled(false); //返回登陆界面 ClientLogin frame = new ClientLogin(); frame.setVisible(true); setVisible(false); } else { throw new Exception("密码为空"); } } else { throw new Exception("密码不同"); } }}
相对应的登录块
package hfz.Login.cn;public class ClientLogin extends JFrame implements ActionListener{ //窗口 private JLabel UserName; private JLabel UserPwd; private JPasswordField txtUserPwd; public JTextField txtUserName; private JButton Login; private JButton Register; private JButton Cancel; private PrintWriter writer; private BufferedReader reader; JLabel imagePos; public ClientLogin(){ this.setTitle("欢迎使用聊天室"); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Font font=new Font("宋体",Font.PLAIN,12); //组件 UserName=new JLabel("用户名:"); UserName.setFont(font); UserPwd=new JLabel("密码:"); UserPwd.setFont(font); txtUserPwd=new JPasswordField(); txtUserName=new JTextField(); Icon image = new ImageIcon("image/1.jpg"); imagePos = new JLabel(image); //按钮 //设置按钮组件 Login=new JButton("登录"); Login.setFont(font); Login.setBackground(new Color(0,155,0)); Login.setToolTipText("进入聊天界面 "); Login.addActionListener(this); Register=new JButton("注册"); Register.setFont(font); Register.setBackground(new Color(0,155,0)); Register.setToolTipText(" 进入注册界面 "); Register.addActionListener(this); Cancel=new JButton("取消"); Cancel.setFont(font); Cancel.setBackground(new Color(0,155,0)); Cancel.setToolTipText(" 清除内容 ") ; Cancel.addActionListener(this); //添加组件 JPanel panel=new JPanel(); getContentPane().add(panel); panel.setLayout(null); UserName.setBounds(new Rectangle(40, 20, 60, 20));//点击会出现矩形框 txtUserName.setBounds(new Rectangle(100, 20, 180, 20)); UserPwd.setBounds(new Rectangle(40, 60, 60, 20)); txtUserPwd.setBounds(new Rectangle(100, 60, 180, 20)); Login.setBounds(new Rectangle(40,100,60,20)); Register.setBounds(new Rectangle(130,100,60,20)); Cancel.setBounds(new Rectangle(220,100,60,20)); imagePos.setBounds(new Rectangle(0,0,320,160)); //把各组件加到框架窗口中 panel.add(UserName); panel.add(UserPwd); panel.add(txtUserName); panel.add(txtUserPwd); panel.add(Login); panel.add(Register); panel.add(Cancel); panel.add(imagePos); setResizable(false); setSize(320,160); Dimension us = this.getSize(); //获取屏幕的尺寸 Dimension them = Toolkit.getDefaultToolkit().getScreenSize(); int newX = (them.width - us.width) / 2 ; int newY = (them.height - us.height) / 2 ; this.setLocation(newX,newY); setVisible(true); } //监听 @Override public void actionPerformed(ActionEvent even){ JButton obj=(JButton)even.getSource(); if(obj==Cancel){ //取消 txtUserName.setText(null); txtUserPwd.setText(null); dispose(); } else if (obj==Login){ //提交 String n=txtUserName.getText(); String p=String.valueOf(txtUserPwd.getPassword()); if(n.length()==0&&p.length()!=0){ JOptionPane.showMessageDialog(this,"您没有输入姓名","提示!",JOptionPane.CANCEL_OPTION); return; } else if (n.length()!=0&&p.length()==0){ JOptionPane.showMessageDialog(this,"您没有输入密码","提示!",JOptionPane.CANCEL_OPTION); return; } else if (n.length()==0&&p.length()==0){ JOptionPane.showMessageDialog(this,"您没有输入姓名和密码","提示!",JOptionPane.CANCEL_OPTION); return; } //调用用户登陆方法 Properties userPro = new Properties(); File file = new File("hfz.properties"); CatUtil.loadPro(userPro, file); String u_nameString=txtUserName.getText(); //System.out.println(nameString); if (file.length()!=0) { if (userPro.containsKey(u_nameString)) { String u_pwd=new String( txtUserPwd.getPassword()); if (u_pwd.equals(userPro.getProperty(u_nameString))) { Login.setEnabled(false); new Client(u_nameString);// 显示聊天界面 this.setVisible(false); }else { JOptionPane.showMessageDialog(null,"密码错误"); //重置 txtUserPwd.setText(""); txtUserName.requestFocus(); } }else { JOptionPane.showMessageDialog(null,"昵称不存在"); txtUserName.setText(""); txtUserPwd.setText(""); txtUserName.requestFocus(); } }else { JOptionPane.showMessageDialog(null,"昵称不存在"); txtUserName.setText(""); txtUserPwd.setText(""); txtUserName.requestFocus(); } } else if (obj==Register){ //注册 setVisible(false); new hfz.Register.cn.Register(); } }}
客户端
package hfz.Clint.cn;public class Client{ private JFrame frame; private JList userList; private JTextArea textArea; private JTextField textField; private JButton btn_start; private JButton btn_stop; private JButton btn_send; private JButton setFont; //字体面板 private JButton bColor; private JPanel northPanel; private JPanel southPanel; private JScrollPane rightScroll; private JScrollPane leftScroll; private JSplitPane centerSplit; private DefaultListModel listModel; private boolean isConnected = false; private Socket socket; private PrintWriter writer; private BufferedReader reader; private MessageThread messageThread;// 负责接收消息的线程 private Map<String, User> onLineUsers = new HashMap<String, User>();// 所有在线用户 // 执行发送 public void send() { if (!isConnected) { JOptionPane.showMessageDialog(frame, "还没有连接服务器,无法发送消息!", "错误", JOptionPane.ERROR_MESSAGE); return; } String message = textField.getText().trim(); if (message == null || message.equals("")) { JOptionPane.showMessageDialog(frame, "消息不能为空!", "错误", JOptionPane.ERROR_MESSAGE); return; } sendMessage(frame.getTitle() + "@" + "ALL" + "@" + message); textField.setText(null); } // 构造方法 public Client(final String username) { Font f = new Font("宋体",Font.PLAIN,12); textArea = new JTextArea(); textArea.setEditable(false); textArea.setForeground(Color.red); textField = new JTextField(); btn_start = new JButton("连接"); btn_stop = new JButton("断开"); btn_send = new JButton("发送"); setFont=new JButton("文字大小"); setFont.setToolTipText("☆点击选择字体☆"); setFont.addActionListener(new FontSet()); bColor=new JButton("字体颜色"); bColor.setToolTipText("☆选择颜色☆"); bColor.addActionListener(new setColor()); listModel = new DefaultListModel(); userList = new JList(listModel); northPanel = new JPanel(); northPanel.setLayout(new GridLayout(1, 7)); northPanel.add(new JLabel("端口:8888")); northPanel.add(new JLabel("服务器IP:localhost")); northPanel.add(new JLabel("昵称:"+username)); northPanel.add(btn_start); northPanel.add(btn_stop); northPanel.setBorder(new TitledBorder("连接信息")); rightScroll = new JScrollPane(textArea); rightScroll.setBorder(new TitledBorder("消息显示区")); leftScroll = new JScrollPane(userList); leftScroll.setBorder(new TitledBorder("在线用户")); southPanel = new JPanel(new BorderLayout()); southPanel.add(setFont,"North"); southPanel.add(bColor,"Center"); southPanel.add(textField,"South"); southPanel.add(btn_send, "East"); southPanel.setBorder(new TitledBorder("写消息")); centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftScroll, rightScroll); centerSplit.setDividerLocation(100); frame = new JFrame("破产版聊天器"); // 更改JFrame的图标: frame.setLayout(new BorderLayout()); frame.add(northPanel, "North"); frame.add(centerSplit, "Center"); frame.add(southPanel, "South"); frame.setSize(600, 400); int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width; int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height; frame.setLocation((screen_width - frame.getWidth()) / 2, (screen_height - frame.getHeight()) / 2); frame.setVisible(true); // 写消息的文本框中按回车键时事件 textField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { send(); } }); // 单击发送按钮时事件 btn_send.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { send(); } }); // 单击连接按钮时事件 btn_start.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String name=username; boolean flag = connectServer(name); if (flag == false) { try { throw new Exception("与服务器连接失败!"); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } frame.setTitle(name); JOptionPane.showMessageDialog(frame, "成功连接!"); } }); // 单击断开按钮时事件 btn_stop.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (!isConnected) { JOptionPane.showMessageDialog(frame, "已处于断开状态,不要重复断开!", "错误", JOptionPane.ERROR_MESSAGE); return; } try { boolean flag = closeConnection();// 断开连接 if (flag == false) { throw new Exception("断开连接发生异常!"); } JOptionPane.showMessageDialog(frame, "成功断开!"); } catch (Exception exc) { JOptionPane.showMessageDialog(frame, exc.getMessage(), "错误", JOptionPane.ERROR_MESSAGE); } } }); // 关闭窗口时事件 frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { if (isConnected) { closeConnection();// 关闭连接 } System.exit(0);// 退出程序 } }); } //颜色 class setColor implements ActionListener{ public void actionPerformed(ActionEvent e){ Object obj = e.getSource(); if(obj==(JButton)bColor){ Color ch = JColorChooser.showDialog(null,"Swing颜色选取器",getForeground()); if(ch != null){ textArea.setForeground(ch); bColor.setBackground(ch); } } } private Color getForeground() { // TODO Auto-generated method stub return null; } } //字体 class FontSet implements ActionListener{ public void actionPerformed(ActionEvent e){ Object obj = e.getSource(); if(obj== (JButton)setFont) setFont(); //调用设置字体方法 } } public void setFont(){ FontChooser fChooser = new FontChooser(frame); fChooser.setVisible(true); Font myNewFont = fChooser.getSelectedFont(); textArea.setFont(myNewFont); fChooser.dispose(); } /** * 连接服务器 * * @param port * @param hostIp * @param u_nameString2 */ public boolean connectServer(String name) { // 连接服务器 try { socket = new Socket("localhost",8888);// 根据端口号和服务器ip建立连接 writer = new PrintWriter(socket.getOutputStream()); reader = new BufferedReader(new InputStreamReader(socket .getInputStream())); // 发送客户端用户基本信息(用户名和ip地址) sendMessage(name); // 开启接收消息的线程 messageThread = new MessageThread(reader, textArea); messageThread.start(); isConnected = true;// 已经连接上了 return true; } catch (Exception e) { textArea.append("连接失败"+"\r\n"); isConnected = false;// 未连接上 return false; } } /** * 发送消息 * * @param message */ public void sendMessage(String message) { writer.println(message); writer.flush(); } /** * 客户端主动关闭连接 */ @SuppressWarnings("deprecation") public synchronized boolean closeConnection() { try { sendMessage("CLOSE");// 发送断开连接命令给服务器 messageThread.stop();// 停止接受消息线程 // 释放资源 if (reader != null) { reader.close(); } if (writer != null) { writer.close(); } if (socket != null) { socket.close(); } isConnected = false; return true; } catch (IOException e1) { e1.printStackTrace(); isConnected = true; return false; } } // 不断接收消息的线程 class MessageThread extends Thread { private BufferedReader reader; private JTextArea textArea; // 接收消息线程的构造方法 public MessageThread(BufferedReader reader, JTextArea textArea) { this.reader = reader; this.textArea = textArea; } // 被动的关闭连接 public synchronized void closeCon() throws Exception { // 清空用户列表 listModel.removeAllElements(); // 被动的关闭连接释放资源 if (reader != null) { reader.close(); } if (writer != null) { writer.close(); } if (socket != null) { socket.close(); } isConnected = false;// 修改状态为断开 } public void run() { String message = ""; while (true) { try { message = reader.readLine(); StringTokenizer stringTokenizer = new StringTokenizer( message, "/@"); String command = stringTokenizer.nextToken();// 命令 if (command.equals("CLOSE"))// 服务器已关闭命令 { textArea.append("服务器已关闭!\r\n"); closeCon();// 被动的关闭连接 return;// 结束线程 } else if (command.equals("ADD")) {// 有用户上线更新在线列表 String username = ""; //String userIp = ""; if ((username = stringTokenizer.nextToken()) != null) { User user = new User(username); onLineUsers.put(username, user); listModel.addElement(username); } } else if (command.equals("DELETE")) {// 有用户下线更新在线列表 String username = stringTokenizer.nextToken(); User user = (User) onLineUsers.get(username); onLineUsers.remove(user); listModel.removeElement(username); } else if (command.equals("USERLIST")) {// 加载在线用户列表 int size = Integer .parseInt(stringTokenizer.nextToken()); String username = null; // String userIp = null; for (int i = 0; i < size; i++) { username = stringTokenizer.nextToken(); // userIp = stringTokenizer.nextToken(); User user = new User(username); onLineUsers.put(username, user); listModel.addElement(username); } } else if (command.equals("MAX")) {// 人数已达上限 textArea.append(stringTokenizer.nextToken() + stringTokenizer.nextToken() + "\r\n"); closeCon();// 被动的关闭连接 JOptionPane.showMessageDialog(frame, "服务器缓冲区已满!", "错误", JOptionPane.ERROR_MESSAGE); return;// 结束线程 } else {// 普通消息 textArea.append(message + "\r\n"); } } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } } }}
服务端
package hfz.Server.cn;public class Server { private JFrame frame; private JTextArea contentArea; private JTextField txt_max; //private JTextField txt_port; private JButton btn_start; private JButton btn_stop; private JPanel northPanel; private JScrollPane rightPanel; private JScrollPane leftPanel; private JSplitPane centerSplit; private JList userList; private DefaultListModel listModel; private ServerSocket serverSocket; private ServerThread serverThread; private ArrayList<ClientThread> clients; private boolean isStart = false; // 主方法,程序执行入口 public static void main(String[] args) { new Server(); } // 构造放法 public Server() { frame = new JFrame("终端显示"); contentArea = new JTextArea(); contentArea.setEditable(false); contentArea.setForeground(Color.blue); txt_max = new JTextField("10"); //txt_port = new JTextField("8888"); btn_start = new JButton("启动"); btn_stop = new JButton("停止"); btn_stop.setEnabled(false); listModel = new DefaultListModel(); userList = new JList(listModel); leftPanel = new JScrollPane(userList); leftPanel.setBorder(new TitledBorder("在线用户")); rightPanel = new JScrollPane(contentArea); rightPanel.setBorder(new TitledBorder("消息显示")); centerSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel); centerSplit.setDividerLocation(100); northPanel = new JPanel(); northPanel.setLayout(new GridLayout(1, 6)); northPanel.add(new JLabel("人数上限")); northPanel.add(txt_max); northPanel.add(new JLabel("端口:8888")); //northPanel.add(txt_port); northPanel.add(btn_start); northPanel.add(btn_stop); northPanel.setBorder(new TitledBorder("配置信息")); frame.setLayout(new BorderLayout()); frame.add(northPanel, "North"); frame.add(centerSplit, "Center"); frame.setSize(400, 200); //frame.setSize(Toolkit.getDefaultToolkit().getScreenSize());//设置全屏 int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width; int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height; frame.setLocation((screen_width - frame.getWidth()) / 2, (screen_height - frame.getHeight()) / 2); frame.setVisible(true); // 关闭窗口时事件 frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { if (isStart) { closeServer();// 关闭服务器 } System.exit(0);// 退出程序 } }); // 单击启动服务器按钮时事件 btn_start.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (isStart) { JOptionPane.showMessageDialog(frame, "服务器已处于启动状态,不要重复启动!", "错误", JOptionPane.ERROR_MESSAGE); return; } int max; //int port; try { try { max = Integer.parseInt(txt_max.getText()); } catch (Exception e1) { throw new Exception("人数上限为正整数!"); } if (max <= 0) { throw new Exception("人数上限为正整数!"); } serverStart(max); contentArea.append("服务器已成功启动!人数上限:" + max + "\r\n"); JOptionPane.showMessageDialog(frame, "服务器成功启动!"); btn_start.setEnabled(false); txt_max.setEnabled(false); // txt_port.setEnabled(false); btn_stop.setEnabled(true); } catch (Exception exc) { JOptionPane.showMessageDialog(frame, exc.getMessage(), "错误", JOptionPane.ERROR_MESSAGE); } } }); // 单击停止服务器按钮时事件 btn_stop.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (!isStart) { JOptionPane.showMessageDialog(frame, "服务器还未启动,无需停止!", "错误", JOptionPane.ERROR_MESSAGE); return; } try { closeServer(); btn_start.setEnabled(true); txt_max.setEnabled(true); // txt_port.setEnabled(true); btn_stop.setEnabled(false); contentArea.append("服务器成功停止!\r\n"); JOptionPane.showMessageDialog(frame, "服务器成功停止!"); } catch (Exception exc) { JOptionPane.showMessageDialog(frame, "停止服务器发生异常!", "错误", JOptionPane.ERROR_MESSAGE); } } }); } // 启动服务器 public void serverStart(int max) throws java.net.BindException { try { clients = new ArrayList<ClientThread>(); serverSocket = new ServerSocket(8888); serverThread = new ServerThread(serverSocket,max); serverThread.start(); isStart = true; } catch (BindException e) { isStart = false; //throw new BindException("端口号已被占用,请换一个!"); } catch (Exception e1) { e1.printStackTrace(); isStart = false; throw new BindException("启动服务器异常!"); } } // 关闭服务器 @SuppressWarnings("deprecation") public void closeServer() { try { if (serverThread != null) serverThread.stop();// 停止服务器线程 for (int i = clients.size() - 1; i >= 0; i--) { // 给所有在线用户发送关闭命令 clients.get(i).getWriter().println("CLOSE"); clients.get(i).getWriter().flush(); // 释放资源 clients.get(i).stop();// 停止此条为客户端服务的线程 clients.get(i).reader.close(); clients.get(i).writer.close(); clients.get(i).socket.close(); clients.remove(i); } if (serverSocket != null) { serverSocket.close();// 关闭服务器端连接 } listModel.removeAllElements();// 清空用户列表 isStart = false; } catch (IOException e) { e.printStackTrace(); isStart = true; } } // 群发服务器消息 public void sendServerMessage(String message) { for (int i = clients.size() - 1; i >= 0; i--) { clients.get(i).getWriter().println("服务器:" + message + "(多人发送)"); clients.get(i).getWriter().flush(); } } // 服务器线程 class ServerThread extends Thread { private ServerSocket serverSocket; private int max;// 人数上限 // 服务器线程的构造方法 public ServerThread(ServerSocket serverSocket,int max) { this.serverSocket = serverSocket; this.max = max; } public void run() { while (true) {// 不停的等待客户端的链接 try { Socket socket = serverSocket.accept(); if (clients.size() == max) {// 如果已达人数上限 BufferedReader r = new BufferedReader( new InputStreamReader(socket.getInputStream())); PrintWriter w = new PrintWriter(socket .getOutputStream()); // 接收客户端的基本用户信息 String inf = r.readLine(); StringTokenizer st = new StringTokenizer(inf, "@"); User user = new User(st.nextToken()); // 反馈连接成功信息 w.println("MAX@服务器:对不起," + user.getName() + ",服务器在线人数已达上限,请稍后尝试连接!"); w.flush(); // 释放资源 r.close(); w.close(); socket.close(); continue; } ClientThread client = new ClientThread(socket); client.start();// 开启对此客户端服务的线程 clients.add(client); listModel.addElement(client.getUser().getName());// 更新在线列表 contentArea.append(client.getUser().getName() + "上线!\r\n"); } catch (IOException e) { e.printStackTrace(); } } } } // 为一个客户端服务的线程 class ClientThread extends Thread { private Socket socket; private BufferedReader reader; private PrintWriter writer; private User user; public BufferedReader getReader() { return reader; } public PrintWriter getWriter() { return writer; } public User getUser() { return user; } // 客户端线程的构造方法 public ClientThread(Socket socket) { try { this.socket = socket; reader = new BufferedReader(new InputStreamReader(socket .getInputStream())); writer = new PrintWriter(socket.getOutputStream()); // 接收客户端的基本用户信息 String inf = reader.readLine(); StringTokenizer st = new StringTokenizer(inf, "@"); user = new User(st.nextToken()); // 反馈连接成功信息 writer.println(user.getName() + "与服务器连接成功!"); writer.flush(); // 反馈当前在线用户信息 if (clients.size() > 0) { String temp = ""; for (int i = clients.size() - 1; i >= 0; i--) { temp += (clients.get(i).getUser().getName() + "/" ) + "@"; } writer.println("USERLIST@" + clients.size() + "@" + temp); writer.flush(); } // 向所有在线用户发送该用户上线命令 for (int i = clients.size() - 1; i >= 0; i--) { clients.get(i).getWriter().println( "ADD@" + user.getName()); clients.get(i).getWriter().flush(); } } catch (IOException e) { e.printStackTrace(); } } @SuppressWarnings("deprecation") public void run() {// 不断接收客户端的消息,进行处理。 String message = null; while (true) { try { message = reader.readLine();// 接收客户端消息 if (message.equals("CLOSE"))// 下线命令 { contentArea.append(this.getUser().getName() + "下线!\r\n"); // 断开连接释放资源 reader.close(); writer.close(); socket.close(); // 向所有在线用户发送该用户的下线命令 for (int i = clients.size() - 1; i >= 0; i--) { clients.get(i).getWriter().println( "DELETE@" + user.getName()); clients.get(i).getWriter().flush(); } listModel.removeElement(user.getName());// 更新在线列表 // 删除此条客户端服务线程 for (int i = clients.size() - 1; i >= 0; i--) { if (clients.get(i).getUser() == user) { ClientThread temp = clients.get(i); clients.remove(i);// 删除此用户的服务线程 temp.stop();// 停止这条服务线程 return; } } } else { dispatcherMessage(message);// 转发消息 } } catch (IOException e) { e.printStackTrace(); } } } // 转发消息 public void dispatcherMessage(String message) { StringTokenizer stringTokenizer = new StringTokenizer(message, "@"); String source = stringTokenizer.nextToken(); String owner = stringTokenizer.nextToken(); String content = stringTokenizer.nextToken(); message = source + "说:" + content; contentArea.append(message + "\r\n"); if (owner.equals("ALL")) {// 群发 for (int i = clients.size() - 1; i >= 0; i--) { clients.get(i).getWriter().println(message); clients.get(i).getWriter().flush(); } } } } }
主类:先开启服务,再登录连接
package hfz.main.cn;import hfz.Login.cn.ClientLogin;public class Test { public static void main(String[] args) { new ClientLogin().txtUserName.getText(); }}
PS:自己也是新人,当时学这个知识点,没打算停留,啥的界面,排布都不怎么好看,当然也感谢其他朋友文档参考(时间有点久,不记得地址了,抱歉),当然,做的还是有自己风味,也希望自己越学越好吧。
代码资源地址补上,也感谢支持:
javaSocket简单聊天室
0 0
- java socket简易聊天室
- Java简易聊天室程序socket
- java菜鸟 socket简易局域网聊天室
- socket简易聊天室
- 安卓 socket简易聊天室
- 使用Socket构建简易聊天室
- Socket编程实现简易聊天室
- Java简易聊天室
- JAVA--简易聊天室程序
- java简易多用户聊天室
- java简易聊天室
- 多线程Java简易聊天室
- C#简易版Socket聊天室 附源码
- Socket套接字做简易聊天室
- 基于Socket的局域网简易聊天室
- socket详解及简易聊天室编写
- php基于websocket搭建简易聊天室(socket)
- 聊天室--java socket
- 栈的解析及C++实现
- Python NLTK 学习笔记1
- Android中点击事件的4中写法
- 桶排序(bucket sort)
- 路由配置与管理——ISIS路由配置与管理3
- java socket简易聊天室
- SpringBoot -- thymeleaf
- weget 下载整个网站
- (c++)求以下三数的和,保留2位小数 1~a之和 1~b的平方和 1~c的倒数和(100 50 10)
- Node.js 通过http调用外部接口
- 设置Framework版本号
- 畅通工程(克鲁斯卡尔算法)
- 大三寒假(2017.1.18)
- Eclipse m2e pom报错:org.apache.maven.archiver.MavenArchiver.getManifest(org.apache.maven.project.Mav