博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
QQ简易版
阅读量:6499 次
发布时间:2019-06-24

本文共 23496 字,大约阅读时间需要 78 分钟。

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
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 + "\r\n");        show.append(content + "\r\n");    }}
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
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
sockets; public QQservice(Socket socket, Map
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
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
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
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
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();    }}

 

转载于:https://www.cnblogs.com/houtian2333/p/10702910.html

你可能感兴趣的文章
JQuery页面随滚动条动态加载效果实现
查看>>
使用PostgreSQL 9.6 架设mediawiki服务器
查看>>
数据库服务器硬件对性能的影响
查看>>
LVM
查看>>
windows+群辉服务器环境下,搭建git版本管理
查看>>
Boolean类型
查看>>
Ubuntu 修改源
查看>>
php 几个比较实用的函数
查看>>
(译)OpenGL ES2.0 – Iphone开发指引
查看>>
@RestController 与 @RequestMapping
查看>>
黑马程序员.bobo.DAY.1
查看>>
Unity shader 官网文档全方位学习(二)
查看>>
pbrun
查看>>
浏览器加载和渲染网页顺序
查看>>
微服务架构springcloud
查看>>
深入剖析Android系统试读样章
查看>>
测试用例出错重跑--flaky插件
查看>>
yaf的安装
查看>>
比较java与C++的不同
查看>>
Twitter Storm入门
查看>>