QQ简易版
Posted houtian2333
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QQ简易版相关的知识,希望对你有一定的参考价值。
package QQ; /* * * 登录界面 * */ import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; public class QQLogin extends JFrame { public QQLogin() { setTitle("登录"); setSize(300, 200); setLocationRelativeTo(null);//设置居中 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(null); JLabel usernameText = new JLabel("账号"); usernameText.setBounds(30, 30, 60, 30); JLabel passwordText = new JLabel("密码"); passwordText.setBounds(30, 60, 60, 30); add(usernameText); add(passwordText); final JTextField username = new JTextField(); final JPasswordField password = new JPasswordField(); username.setBounds(100, 30, 120, 30); password.setBounds(100, 60, 120, 30); add(username); add(password); //注册按钮 JButton reg=new JButton("注册"); reg.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { new QQReg().setVisible(true);//打开注册页面 QQLogin.this.dispose();//关闭登录页面 } }); reg.setBounds(150,110,80,30); add(reg); //登录 JButton login = new JButton("登录"); login.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { //获取账号密码 Message message = new Message(); message.setType(Message.LOGIN); //获取注注册类型 message.setUsername(username.getText());//获取输入框输入名称 message.setPassword(new String(password.getPassword())); //获取输入框输入密码 try { Socket socket = new Socket("127.0.0.1", 8888); //连接服务器 ObjectRW.writeObject(message, socket); //调用ObjectRW的静态方法writeObject 并把message, socket的对象传入进去调用方法之后传入到服务器 message = (Message) ObjectRW.readObject(socket); //调用ObjectRW中的readObject方法 获取message信息 if (message.getType() == Message.RESULT && message.isSuccess()) { //弹窗 // JOptionPane.showConfirmDialog(null, "登录成功", "提示", JOptionPane.YES_OPTION); QQLogin.this.setVisible(false);//隐藏登录界面 new Friends(socket,username.getText()).setVisible(true); // QQLogin.this.dispose(); //开启friends列表界面 并将登录时的socket和名称传过去 } else { JOptionPane.showConfirmDialog(null, "登录失败", "提示", JOptionPane.YES_OPTION); } } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }); login.setBounds(50, 110, 80, 30); add(login); } }
package QQ; /* * * 注册界面 * */ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPasswordField; import javax.swing.JTextField; public class QQReg extends JFrame { public QQReg() { setTitle("注册"); setSize(300, 200); setLocationRelativeTo(null);//设置居中 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(null); JLabel usernameText = new JLabel("账号"); usernameText.setBounds(30, 30, 60, 30); JLabel passwordText = new JLabel("密码"); passwordText.setBounds(30, 60, 60, 30); add(usernameText); add(passwordText); final JTextField username = new JTextField(); final JPasswordField password = new JPasswordField(); username.setBounds(100, 30, 120, 30); password.setBounds(100, 60, 120, 30); add(username); add(password); //注册按钮 JButton reg = new JButton("注册"); reg.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { //获取账号密码 Message message = new Message(); message.setType(Message.REG); //获取注注册类型 message.setUsername(username.getText());//获取输入框输入名称 message.setPassword(new String(password.getPassword())); //获取输入框输入密码 try { Socket socket = new Socket("127.0.0.1", 8888); //连接服务器 ObjectRW.writeObject(message, socket); //调用ObjectRW的静态方法writeObject 并把message, socket的对象传入进去调用方法之后传入到服务器 message = (Message) ObjectRW.readObject(socket); //调用ObjectRW中的readObject方法 获取message信息 if (message.getType() == Message.RESULT && message.isSuccess()) { //弹窗 // JOptionPane.showConfirmDialog(null, "注册成功", "提示", JOptionPane.OK_OPTION); new QQLogin().setVisible(true); QQReg.this.dispose(); } else { JOptionPane.showConfirmDialog(null, "注册失败", "提示", JOptionPane.YES_OPTION); } } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }); reg.setBounds(100, 110, 80, 30); add(reg); } }
package QQ; import java.io.Serializable; public class Message implements Serializable { private static final long serialVersionUID = -3021746792251923405L; //设为对象流 private int type = 0;//消息类型 public static final int RESULT = 2;//完成为2 public static final int REG = 1;//初始注册 public static final int LOGIN = 3;//登录 private boolean isSuccess;//是否注册成功 public static final int REFRESH_FRIENDS = 4;//刷新好友列表 public static final int REFRESH_FRIENDS_RESULT = 5;//刷新好友列表结果 public static final int SINGLE_MESSAGE = 6;//一对一废话聊天 public static final int GROUP_MESSAGE = 7;//群聊消息 public static final int EXIT =8;//退出程序 private String from;//消息发送者 private String to;//消息接受者 private String content;//消息内容 private String time;//发送时间 public String getFrom() { return from; } public void setFrom(String from) { this.from = from; } public String getTo() { return to; } public void setTo(String to) { this.to = to; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getTime() { return time; } public void setTime(String time) { this.time = time; } private String[] friends;//所有好友数据 public String[] getFriends() { return friends; } public void setFriends(String[] friends) { this.friends = friends; } public boolean isSuccess() { return isSuccess; } public void setSuccess(boolean isSuccess) { this.isSuccess = isSuccess; } public int getType() { return type; } public void setType(int type) { this.type = type; } private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
package QQ; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.Socket; public class ObjectRW { /** * 写出对象 * @param obj * @param socket */ public static void writeObject(Object obj,Socket socket){ //静态 ObjectRW.writeObject(message, socket);传入的是message对象 Object是父类形成一个多态 try { ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); oos.writeObject(obj); //获取socket之后 写出writeObject(obj)写出到服务器的是message里面的信息 } catch (IOException e) { e.printStackTrace(); } } /** * 读取对象 * @param socket * @return */ public static Object readObject(Socket socket){ try { ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); return ois.readObject(); //获取socket之后 从服务器读取所有相关信息 } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; //如果没有就返回为空 } }
package QQ; /* * 好友列表 * */ import sun.applet.resources.MsgAppletViewer; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.net.Socket; import java.util.HashMap; import java.util.Map; public class Friends extends JFrame { private Socket socket; private String username; private JPanel friends;//一个装列表的容器 private String[] all;//用来存放好友列表 private Map<String,Talk> talks = new HashMap<>();//用来存放对话窗口 // 将用户名 和对应的对话窗口放在一个集合中 方便以后调用该窗口 public Friends(Socket socket, String username) { setTitle(username); this.socket = socket; //接受登录时自己的socket this.username = username; ////接受登录时自己的username friends = new JPanel(); friends.setLayout(new BorderLayout()); add(friends); //容器添加到框里去 JButton group =new JButton("群聊"); //------------群聊按钮 group.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { showTalk("群聊",Talk.GROUP); } }); add(group,BorderLayout.SOUTH); // 第一次刷新好友列表 Message msg = new Message(); //从登陆完成之后从内存中获取相关信息 msg.setType(Message.REFRESH_FRIENDS);//设置为刷新类型 ObjectRW.writeObject(msg, socket);//修改之后传入内存中--等待服务器反应 // msg = (Message)ObjectRW.readObject(socket);//从内存中获取从服务器返回的msg包里的信息 // if(msg.getType() == Message.REFRESH_FRIENDS_RESULT){ //判读是否获取列表成功 // refreshFriend(msg); //进行刷新操作 // } ////启动线程随时能够接收服务器发送过来的消息 FriendUtil friendUtil = new FriendUtil(socket, this); ///--->FriendUtil friendUtil.start(); setSize(150, 500); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); //退出 告诉服务器 //添加窗口事件 addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { Message msg =new Message(); msg.setType(Message.EXIT); msg.setUsername(username); ObjectRW.writeObject(msg,socket); System.exit(0);//退出程序 } }); } /** * 刷新 * * @param msg */ public void refreshFriend(Message msg) { friends.removeAll();//移除容器之前中的组件 all =msg.getFriends(); JList list = new JList(all);//将获取到的好友列表信息写入列表中 msg.getFriends()好友列表 //鼠标事件 对好友列表进行操作 list.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { //判断是否双击 if(e.getClickCount()==2){ //根据鼠标位置判断点击的是第几个 int index = list.locationToIndex(e.getPoint());//返回一个数字 //all[index]根据好友列表数组得到接受者 //并打开聊天窗口 showTalk(all[index],Talk.SINGLE); } } }); friends.add(list); friends.repaint(); friends.updateUI();//刷新 } /** * 显示聊天窗口 * @param name */ public Talk showTalk(String name,int type){ //聊天窗口类 Talk talk =talks.get(name); //talks 是聊天窗口的集合 通过名字获得该窗口 if(talk ==null){ //如果之前没有这个窗口就创建一个新的窗口 talk = new Talk(name,socket,username,type);// --------->调用talk构造方法 打开对话窗口方法 talks.put(name,talk); //将接受者的名字和他的窗口放进集合 } if(!talk.isVisible()){ //如果该窗口没有显示才显示窗口 talk.setVisible(true); } return talk; } }
package QQ; /* * * * */ import java.net.Socket; public class FriendUtil extends Thread { private Socket socket; private Friends friends; public FriendUtil(Socket socket, Friends friends) { this.socket = socket; this.friends = friends; } @Override public void run() { //通过friends中线程启动随时能够接收服务器发送过来的消息 super.run(); while (true) { Message msg = (Message) ObjectRW.readObject(socket); if (msg.getType() == Message.REFRESH_FRIENDS_RESULT) { friends.refreshFriend(msg); //刷新每一个的列表 } else if (msg.getType() == Message.SINGLE_MESSAGE) { Talk talk = friends.showTalk(msg.getFrom(), Talk.SINGLE); ///---->>>friends.showTalk msg.getFrom()发送者的名称 //开启一个接受者的窗口并将发送者作为你的窗口的接受者 talk.showMessage(msg.getFrom(), msg.getContent(), msg.getTime()); //---->talk.showMessage在接受者的窗口显示接受消息 } else if (msg.getType() == Message.GROUP_MESSAGE) { Talk talk = friends.showTalk("群聊", Talk.GROUP); ///---->>>friends.showTalk msg.getFrom()发送者的名称 //开启一个接受者的窗口并将发送者作为你的窗口的接受者 talk.showMessage(msg.getFrom(), msg.getContent(), msg.getTime()); } } } }
package QQ; /* * 聊天 * * */ import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; public class Talk extends JFrame { private String to; private Socket socket; private String from; private int type; //-----------区分群聊 public static final int SINGLE = 1;//一对一废话聊天 public static final int GROUP= 2;//群聊消息 private JTextArea show;//消息接受显示框 private JTextArea input;//消息发送显示框 public Talk(String to, Socket socket, String from,int type) { //从Friends中showTalk方法调用该构造方法 talk = new Talk(name,socket,username);//调用talk this.to = to; this.socket = socket; //消息内容所需要的 this.from = from; this.type =type; setSize(200, 350); setLocationRelativeTo(null); setTitle(to); show = new JTextArea(); show.setEditable(false);//设置不可编辑 show.setBorder(BorderFactory.createLineBorder(Color.gray));//设置边框 input = new JTextArea(); JButton btn = new JButton("发送");//发送按钮 btn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Message msg = new Message(); if(type ==Talk.SINGLE){ msg.setType(Message.SINGLE_MESSAGE);//聊天类型 一对一 }else { msg.setType(Message.GROUP_MESSAGE);//聊天类型 群聊 } msg.setFrom(from); msg.setTo(to); msg.setContent(input.getText());//聊天消息内容 content //设置发送时间 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); msg.setTime(sdf.format(new Date()));//发送时当前时间 ObjectRW.writeObject(msg,socket); //写入通道传给服务器 ----->到服务器 showMessage(from,input.getText(),sdf.format(new Date())); //在发送者界面显示已经发送的消息 input.setText("");//发送信息后清空发送框 } }); JScrollPane jsc = new JScrollPane(show); jsc.setPreferredSize(new Dimension(0, 200)); add(jsc,BorderLayout.NORTH); add(new JScrollPane(input),BorderLayout.CENTER); add(btn,BorderLayout.SOUTH); setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); } /* * 显示消息 * */ public void showMessage(String name,String content,String time){ //显示消息 show.append(name); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); show.append(" " + time + " "); show.append(content + " "); } }
package QQ; /* * * 服务器端 * */ import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; import java.util.Map; public class QQserver { ServerSocket serverSocket; private Map<String, Socket> sockets = new HashMap<>();//这里有线程安全的问题 public QQserver() { try { serverSocket = new ServerSocket(8888); } catch (IOException e) { e.printStackTrace(); } } /* * * 开启服务器 * */ public void start() { while (true) { try { Socket socket = serverSocket.accept();//开启 Message msg = (Message) ObjectRW.readObject(socket); if (msg.getType() == Message.REG) { msg.setType(Message.RESULT); msg.setSuccess(reg(msg)); ObjectRW.writeObject(msg, socket); } else if (msg.getType() == Message.LOGIN) { msg.setType(Message.RESULT); boolean flag = login(msg); msg.setSuccess(flag); ObjectRW.writeObject(msg, socket); if(flag){//登录成功之后进行列表信息操作 sockets.put(msg.getUsername(), socket);//保存其余所有登录成功时的通道和用户名到集合里面 //启动一个专门针对一个用户服务的线程 new QQservice(socket,sockets).start(); } } } catch (IOException e) { e.printStackTrace(); } } } /* * 执行注册 * */ public boolean reg(Message msg) { return Sqlutil.reg(msg); } /* * * 执行登录 * */ public boolean login(Message msg) { return Sqlutil.login(msg); } }
package QQ; import java.io.IOException; import java.net.Socket; import java.util.Map; import java.util.Set; public class QQservice extends Thread { private Socket socket; private Map<String, Socket> sockets; public QQservice(Socket socket, Map<String, Socket> sockets) { this.socket = socket; //当前登录并刷新时自己的socket this.sockets = sockets;//其他人登录时保存的username和socket } @Override public void run() { while (true) { //刷新时需要可复用 Message msg = (Message) ObjectRW.readObject(socket);//读取写入内存中的信息 if (msg.getType() == Message.REFRESH_FRIENDS) {//----------判断为获取好友列表操作 msg.setType(Message.REFRESH_FRIENDS_RESULT);//修改刷新完成类型 msg.setFriends(getFriends());//获取好友列表并写入msg中 // ObjectRW.writeObject(msg, socket); 只是刷新给当前登录的那个人 // 刷新给所有人 Set<String> sets = sockets.keySet(); for (String name : sets) { //每次循环 给每个登录的人 ObjectRW.writeObject(msg, sockets.get(name)); //将修改的msg和socket写回每一个人中的内存中 } } else if (msg.getType() == Message.SINGLE_MESSAGE) { //>>>>-------判断为一对一聊天操作读取talk发送过来的内容 Socket to = sockets.get(msg.getTo()); //通过 sockets集合 接受者的sockets (连接方式) ObjectRW.writeObject(msg, to);//将信息发送给需要接受的人 } else if (msg.getType() == Message.GROUP_MESSAGE) {//----------判断为群聊操作 // ObjectRW.writeObject(msg, socket); 只是刷新给当前登录的那个人 // 刷新给所有人 Set<String> sets = sockets.keySet(); for (String name : sets) { //每次循环 给每个登录的人 if (!name.equals(msg.getFrom())) { //不需要给自己发送群聊消息 ObjectRW.writeObject(msg, sockets.get(name)); //将修改的msg和socket写回每一个人中的内存中 } } } else if (msg.getType() == Message.EXIT) { //退出 //从集合中移除 sockets.remove(msg.getUsername()); msg.setType(Message.REFRESH_FRIENDS_RESULT);//修改刷新完成类型 msg.setFriends(getFriends());//获取好友列表并写入msg中 Set<String> sets = sockets.keySet(); for (String name : sets) { //每次循环 给每个登录的人 ObjectRW.writeObject(msg, sockets.get(name)); //将修改的msg和socket写回每一个人中的内存中 } try { socket.close(); } catch (IOException e) { e.printStackTrace(); } break; } } } /** * 获取所有的好友数据 * * @return */ public String[] getFriends() { Set<String> names = sockets.keySet(); //将好友列表的信息设为set集合 String friends[] = new String[names.size()]; names.toArray(friends); //将set中的信息写到集合中去 返回一个好友列表的集合 return friends; } }
package QQ; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; /* * 连接数据库并进行添加操作 * * * */ public class Sqlutil { static { try { //加载驱动 方法块 Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() { try { //连接数据库 return DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false", "root", "123456"); } catch (SQLException e) { e.printStackTrace(); } return null; } //关闭连接 public static void colse(ResultSet rs, PreparedStatement pst, Connection conn) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (pst != null) { try { pst.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } //进行注册功能并写入数据库 public static boolean reg(Message msg) { String sql = "insert into user (user,password)values (?,?)"; Connection conn = getConnection();//调用getConnection()方法 if (conn == null) { System.out.println("连接问题"); return false; } boolean flag = false; PreparedStatement pst = null; try { pst = conn.prepareStatement(sql); pst.setString(1, msg.getUsername()); pst.setString(2, msg.getPassword()); flag = pst.executeUpdate() > 0; } catch (SQLException e) { e.printStackTrace(); } finally { colse(null, pst, conn); } return flag; } public static boolean login(Message msg) { String sql = "select * from user where user= ? and password= ?"; Connection conn = getConnection();//调用getConnection()方法 if (conn == null) { System.out.println("连接问题"); return false; } PreparedStatement pst = null; ResultSet rs = null; boolean flag = false; try { pst = conn.prepareStatement(sql); pst.setString(1, msg.getUsername()); pst.setString(2, msg.getPassword()); rs = pst.executeQuery(); flag = rs.next(); } catch (SQLException e) { e.printStackTrace(); } finally { colse(rs, pst, conn); } return flag; } }
package QQ; public class main { public static void main(String[] args) { // new QQReg().setVisible(true); new QQLogin().setVisible(true); } }
package QQ; public class main2 { public static void main(String[] args) { new QQserver().start(); } }
以上是关于QQ简易版的主要内容,如果未能解决你的问题,请参考以下文章