Java-Java基础10之网络编程实现简易版QQ聊天程序

主要内容有:Java网络编程应用

文件结构

文件结构
文件结构

Myqq功能说明:

要求实现的功能:
    1.把登录界面,好友列表界面,聊天界面实现.
    2.当用户点击登录后,把qq号码和密码发送给QqServer去验证如果该用户合法,则返回ok,如果不合法,则返回err.
    3.完成好友互相聊天功能.
    4.如果好友在线则,显示彩色头像,反之显示色头像.
    5.当好友上线后,则提示.
扩展实现:
    1.实现真的多人聊天,不出现错误.
    2.把接收到的消息,显示到该显示的聊天界面
    3.如果好友在线,则显彩色头像,反之,显示灰色头像
        思路:当一个用户登录成功后,就向服务器发送一个要求返回
        在线好友的包,服务器就回送一个在线好友的信息包。[客户端
        得到这个包后再处理]

        服务器返回
        type:message_ret_onLineFriend;
        con: "3 4 5 6 9 12"

        如何在前面登录的人,知道后面登录人的情况
        思路,让每一个人登陆ok后,就通知其它在线的人,我上线了

要求自己完成:
    1.不让同一个账号反复登录(通过数据库验证)
    2.如果好友不在线,则不能聊天

QQ好友列表布局
QQ好友列表布局

QQ登录验证3层模型
QQ登录验证3层模型

服务端_QqServer/com.qq.server.view/MyServerFrame.java

/**
 * 这 是服务器端的控制界面,可以完成启动服务器,关闭服务器
 * 可以管理和监控用户。
 */
package com.qq.sever.view;
import javax.swing.*;
import com.qq.server.model.*;
import java.awt.*;
import java.awt.event.*;
public class MyServerFrame extends JFrame implements ActionListener{
    JPanel jp1;
    JButton jb1,jb2;
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        MyServerFrame mysf=new MyServerFrame();
    }
    public MyServerFrame()
    {
        jp1=new JPanel();
        jb1=new JButton("启动服务器");
        jb1.addActionListener(this);//监听
        jb2=new JButton("关闭服务器");
        jp1.add(jb1);
        jp1.add(jb2);
        this.add(jp1);
        this.setSize(500,400);
        this.setTitle("Myqq服务器端");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        //判断
        if(e.getSource()==jb1)
        {
            new MyQqServer();
        }
    }
}

服务端_QqServer/com.qq.server.model/QqServerUser.java

package com.qq.server.model;
public class QqServerUser {
}

服务端_QqServer/com.qq.server.model/MyQqServer.java

/**
 * 这是QQ服务器,它在监听,等待某个qq客户端,来连接
 */
package com.qq.server.model;
import java.net.*;
import java.io.*;
import java.util.*;
import com.qq.common.*;
public class MyQqServer {
    public MyQqServer()
    {
        try {
            //在9999监听
            ServerSocket ss=new ServerSocket(9999);
            //System.out.println("服务器在9999监听");
            //阻塞,等待客户端来连接
            while(true)
            {
                Socket s=ss.accept();
                //接收客户端发来的信息
                ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
                User u=(User)ois.readObject();
                //System.out.println("服务器接收到用户名id:"+u.getUserId()+" 密码:"+u.getPassWd());
                //返回一个成功登陆的信息包
                Message m=new Message();
                ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
                if(u.getPassWd().equals("123456"))
                {
                    m.setMesType("1");
                    oos.writeObject(m);
                    //这里就单开一个线程,让该线程与该客户端保持通信
                    SerConClientThread scct=new SerConClientThread(s);
                    ManageClientThread.addClientThread(u.getUserId(), scct);
                    scct.start();//启动与该客户端通信的线程
                    //并通知其它在线用户
                    scct.notifyOther(u.getUserId());
                }else{
                    m.setMesType("2");
                    oos.writeObject(m);
                    //关闭连接
                    s.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

服务端_QqServer/com.qq.server.model/ ManageClientThread.java

/**
 * 管理客户端的线程
 */
package com.qq.server.model;
import java.util.*;
public class ManageClientThread {
    public static HashMap<String, SerConClientThread> hm=new HashMap<String,SerConClientThread>();
    //向hm中添加一个客户端通讯线程
    public static void addClientThread(String uid,SerConClientThread ct)
    {
        hm.put(uid,ct);
    }
    public static SerConClientThread getClientThread(String uid)
    {
        return(SerConClientThread)hm.get(uid);
    }
    //返回当前在线的人的情况
    public static String getAllOnLineUserid()
    {
        //使用迭代器完成对HashMap的keys的遍历
        Iterator it=hm.keySet().iterator();
        String res="";
        while(it.hasNext())
        {
            res+=it.next().toString()+" ";
        }
        return res;
    }
}

服务端_QqServer/com.qq.server.model/ SerConClientThread.java

/**
 * 功能:是服务器和某个客户端的通讯线程
 */
package com.qq.server.model;
import java.net.*;
import java.util.HashMap;
import java.util.Iterator;
import java.io.*;
import com.qq.common.*;
public class SerConClientThread extends Thread{
    Socket s;
    public SerConClientThread(Socket s)
    {
        //把服务器和该客户端连接赋给s
        this.s=s;
    }
    //让该线程去通知其它用户
    public void notifyOther(String iam)
    {
        //得到所有在线的人的线程
        HashMap hm=ManageClientThread.hm;
        Iterator it=hm.keySet().iterator();
        while(it.hasNext())
        {
            Message m=new Message();
            m.setCon(iam);
            m.setMesType(MessageType.message_ret_onLineFriend);
            //取出在线人的id
            String onLineUserId=it.next().toString();
            try {
                ObjectOutputStream oos=new ObjectOutputStream(ManageClientThread.
                        getClientThread(onLineUserId).s.getOutputStream());
                m.setGetter(onLineUserId);
                oos.writeObject(m);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    public void run()
    {
        while(true)
        {
            try {
                //这里该线程就可以接收客户端的信息
                ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
                Message m=(Message)ois.readObject();
                //System.out.println(m.getSender()+"给"+m.getGetter()+"说:"+m.getCon());
                //转发
                //从客户端取得的消息进行类型判断,然后做相应的处理
                if(m.getMesType().equals(MessageType.message_comm_mes))
                {
                    //取得接收人的通信线程
                    SerConClientThread sc=ManageClientThread.getClientThread(m.getGetter());
                    ObjectOutputStream oos=new ObjectOutputStream(sc.s.getOutputStream());
                    oos.writeObject(m);
                }
                else if(m.getMesType().equals(MessageType.message_get_onLineFriend))
                {
                    //System.out.println(m.getSender()+" 要他的好友");
                    //把在服务器的好友给该客户端返回
                    String res=ManageClientThread.getAllOnLineUserid();
                    Message m2=new Message();
                    m2.setMesType(MessageType.message_ret_onLineFriend);
                    m2.setCon(res);
                    m2.setGetter(m.getSender());
                    ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
                    oos.writeObject(m2);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

服务端_QqServer/com.qq.common/ Message.java

/**
 * 对Message规定一些规则
 * mesType1->表示是登陆成功
 * mesType2->表示是登陆失败
 * mesType3->表示是普通的消息包
 */
package com.qq.common;
public class Message implements java.io.Serializable{
    private String mesType;
    private String sender;
    private String getter;
    private String con;
    private String sendTime;
    public String getSender() {
        return sender;
    }
    public void setSender(String sender) {
        this.sender = sender;
    }
    public String getGetter() {
        return getter;
    }
    public void setGetter(String getter) {
        this.getter = getter;
    }
    public String getCon() {
        return con;
    }
    public void setCon(String con) {
        this.con = con;
    }
    public String getSendTime() {
        return sendTime;
    }
    public void setSendTime(String sendTime) {
        this.sendTime = sendTime;
    }
    public String getMesType() {
        return mesType;
    }
    public void setMesType(String mesType) {
        this.mesType = mesType;
    }
}

服务端_QqServer/com.qq.common/ MessageType.java

/**
 * 定义消息包的种类
 */
package com.qq.common;
public interface MessageType {
    String message_succeed="1";//登录成功
    String message_login_fail="2";//登录失败
    String message_comm_mes="3";//普通信息包
    String message_get_onLineFriend="4";//请求在线好友的信息包
    String message_ret_onLineFriend="5";//返回在线好友的信息包
}

服务端_QqServer/com.qq.common/ User.java

/**
 * 这是用户信息类
 */
package com.qq.common;
public class User implements java.io.Serializable{
    //将这个类序列化,就使其对应的对象可以在网络上或者是在文件中传输
    private String userId;
    private String passWd;
    public String getUserId() {
        return userId;
    }
    public void setUserId(String userId) {
        this.userId = userId;
    }
    public String getPassWd() {
        return passWd;
    }
    public void setPassWd(String passWd) {
        this.passWd = passWd;
    }
}

服务端_QqServer/com.qq.server.db/ SqlHelper.java

package com.qq.server.db;
public class SqlHelper {
}

客户端_QqServer/com.qq.client.view/QqClientLogin.java

/**
 * 功能:qq客户端登录界面
 */
package com.qq.client.view;
import javax.swing.*;
import java.io.*;
import com.qq.client.tools.*;
import com.qq.cllient.model.*;
import com.qq.common.*;
import java.awt.*;
import java.awt.event.*;
public class QqClientLogin extends JFrame implements ActionListener{
    //定义北部需要的组件
    JLabel jbl1;
    //定义中部需要的组件
    //中部有三个JPanel,由一个选项卡窗口管理
    JTabbedPane jtp;
    JPanel jp2,jp3,jp4; //jp2放qq号码输入
    JLabel jp2_jbl1,jp2_jbl2,jp2_jbl3,jp2_jbl4;
    JButton jp2_jb1;
    JTextField jp2_jtf;
    JPasswordField jp2_jpf;
    JCheckBox jp2_jcb1,jp2_jcb2;
    //定义南部需要的组件
    JPanel jp1;
    JButton jp1_jb1,jp1_jb2,jp1_jb3;
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        QqClientLogin qqClientLogin=new QqClientLogin();
    }
    public QqClientLogin()
    {
        //处理北部
        jbl1=new JLabel(new ImageIcon("image/tou.gif"));
        //处理中部
        jp2=new JPanel(new GridLayout(3,3));
        jp2_jbl1=new JLabel("QQ号码",JLabel.CENTER);
        jp2_jbl2=new JLabel("QQ密码",JLabel.CENTER);
        jp2_jbl3=new JLabel("忘记密码",JLabel.CENTER);
        jp2_jbl3.setForeground(Color.blue);
        jp2_jbl4=new JLabel("申请密码保护",JLabel.CENTER);
        jp2_jb1=new JButton(new ImageIcon("image/clear.gif"));
        jp2_jtf=new JTextField();
        jp2_jpf=new JPasswordField();
        jp2_jcb1=new JCheckBox("隐身登录");
        jp2_jcb2=new JCheckBox("记住密码");
        //把控件按照顺序加入到jp2
        jp2.add(jp2_jbl1);
        jp2.add(jp2_jtf);
        jp2.add(jp2_jb1);
        jp2.add(jp2_jbl2);
        jp2.add(jp2_jpf);
        jp2.add(jp2_jbl3);;
        jp2.add(jp2_jcb1);
        jp2.add(jp2_jcb2);
        jp2.add(jp2_jbl4);
        jtp=new JTabbedPane();//创建选项卡窗口
        jtp.add("QQ号码",jp2);
        jp3=new JPanel();
        jtp.add("手机号码",jp3);
        jp4=new JPanel();
        jtp.add("电子邮件",jp4);
        //处理南部
        jp1=new JPanel();
        jp1_jb1=new JButton(new ImageIcon("image/denglu.gif"));
        //响应用户点击登录
        jp1_jb1.addActionListener(this);
        jp1_jb2=new JButton(new ImageIcon("image/quxiao.gif"));
        jp1_jb3=new JButton(new ImageIcon("image/xiangdao.gif"));
        //把三个按钮放入到jp1
        jp1.add(jp1_jb1);
        jp1.add(jp1_jb2);
        jp1.add(jp1_jb3);
        this.add(jbl1,"North");    //北部
        this.add(jtp,"Center");
        this.add(jp1,"South");    //南部
        this.setSize(350,240);
        this.setTitle("QQ登录");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        //如果要用户点击了登录
        if(e.getSource()==jp1_jb1)
        {
            QqClientUser qqClientUser=new QqClientUser();
            User u=new User();
            u.setUserId(jp2_jtf.getText().trim());
            u.setPassWd(new String(jp2_jpf.getPassword()));
            if(qqClientUser.checkUser(u))
            {
                try {
                    //创建好友列表
                    QqFriendList qqList=new QqFriendList(u.getUserId());
                    //并将登录成功的加入到好友列表
                    ManageQqFriendList.addQqFrendList(u.getUserId(), qqList);
                    //发送一个要求返回在线好友的请求包
                    ObjectOutputStream oos=new ObjectOutputStream
                            (ManageClientConServerThread.getClientConServerThread
                                    (u.getUserId()).getS().getOutputStream());
                    //做一个message包
                    Message m=new Message();
                    //指明包的类型
                    m.setMesType(MessageType.message_get_onLineFriend);
                    //并在包中指明是这个QQ号的好友情况
                    m.setSender(u.getUserId());
                    oos.writeObject(m);
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
                //关闭掉登录界面
                this.dispose();
            }else{
                JOptionPane.showMessageDialog(this, "用户名或密码错误");
            }
        }
    }
}

客户端_QqServer/com.qq.client.view/QqChat.java

/**
 * 与好友聊天的界面
 * 因为客户端,要处于读取的状态,因此我们把它做成一个线程
 */
package com.qq.client.view;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import com.qq.client.tools.*;
import com.qq.cllient.model.*;
import com.qq.common.*;
public class QqChat extends JFrame implements ActionListener{
    JTextArea jta;
    JTextField jtf;
    JButton jb;
    JPanel jp;
    String ownerId;
    String friendId;
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //QqChat qqChat=new QqChat("1");
    }
    public QqChat(String ownerId,String friend)
    {
        this.ownerId=ownerId;
        this.friendId=friend;
        jta=new JTextArea();
        jtf=new JTextField(15);
        jb=new JButton("发送");
        jb.addActionListener(this);//监听
        jp=new JPanel();
        jp.add(jtf);
        jp.add(jb);
        this.add(jta,"Center");
        this.add(jp,"South");
        this.setSize(300,200);
        //this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle(ownerId+" 正在和 "+friend+" 聊天");
        this.setIconImage((new ImageIcon("image/qq.gif")).getImage());
        this.setVisible(true);
        //this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    }
    //写一个方法,让它显示消息
    public void showMessage(Message m)
    {
        //显示
        String info=m.getSender()+" 对"+m.getGetter()+" 说:"+m.getCon()+"\r\n";
        this.jta.append(info);
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        //判断
        if(e.getSource()==jb)
        {
            //如果用户点击了 发送按钮
            Message m=new Message();
            m.setMesType(MessageType.message_comm_mes);
            m.setSender(this.ownerId);
            m.setGetter(this.friendId);
            m.setCon(jtf.getText());
            m.setSendTime(new java.util.Date().toString());
            try {
                //发送给服务器
                ObjectOutputStream oos=new ObjectOutputStream
                        (ManageClientConServerThread.getClientConServerThread(ownerId).getS().getOutputStream());
                //通过管理线程的类取得线程,然后通过线程取得对应线程中的Socket,再通过这个Socket输出流取得Socket中内容
                oos.writeObject(m);//发送
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }
//    @Override
//    public void run() {
//        //读取状态
//        while(true)
//        {
//            //读取[如果读不到就等待]
//            try {
//                ObjectInputStream ois=new ObjectInputStream(QqClientConServer.s.getInputStream());
//                Message m=(Message)ois.readObject();
//                
//                //显示
//                String info=m.getSender()+" 对"+m.getGetter()+" 说:"+m.getCon()+"\r\n";
//                this.jta.append(info);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//            
//        }
//    }
}

客户端_QqServer/com.qq.client.view/QqFriendList.java

/**
 * 我的好友列表,(也包括陌生人,黑名单)
 */
package com.qq.client.view;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import com.qq.client.tools.*;
import com.qq.common.*;
public class QqFriendList extends JFrame implements ActionListener,MouseListener{
    //定义控件
    //第一张卡片(好友)
    JPanel jphy1,jphy2,jphy3;
    JButton jphy_jb1,jphy_jb2,jphy_jb3;
    JScrollPane jsp1;
    //第二张卡片(陌生人)
    JPanel jpmsr1,jpmsr2,jpmsr3;
    JButton jpmsr_jb1,jpmsr_jb2,jpmsr_jb3;
    JScrollPane jsp2;
    JLabel []jbls;
    JLabel []jbls2;
    String owner;
    //把整个JFrame设置成CardLayout布局
    CardLayout cl;
    public static void main(String[] args) {
        //
        //QqFriendList qqFriendList=new QqFriendList();
    }
    //更新在线好友的情况
    public void updateFriend(Message m)
    {
        String onLineFriend[]=m.getCon().split(" ");
        for(int i=0;i<onLineFriend.length;i++)
        {
            //把对应的好友状态设置成在线
            jbls[Integer.parseInt(onLineFriend[i])-1].setEnabled(true);
            //System.out.println("创建了 "+jbls[Integer.parseInt(onLineFriend[i])-1]);
        }
    }
    public QqFriendList(String ownerId)
    {
        this.owner=ownerId;
        //处理第一张卡片(显示好友列表)
        jphy1=new JPanel(new BorderLayout());
        //假定有50个好友(50行,1列,两个4分别表示行间距与列间距)
        jphy2=new JPanel(new GridLayout(50,1,4,4));
        //给jphy2,初始化50好友
        jbls=new JLabel[50];
        for(int i=0;i<jbls.length;i++)
        {
            jbls[i]=new JLabel(i+1+"",new ImageIcon("image/mm.jpg"),JLabel.LEFT);
            jbls[i].addMouseListener(this);//监听每一个好友
            jbls[i].setEnabled(false);//把其它人物设置成不线状态
            if(jbls[i].getText().equals(ownerId))//把自己设置成在线状态
            {
                jbls[i].setEnabled(true);
            }
            jphy2.add(jbls[i]);
        }
        jphy3=new JPanel(new GridLayout(2,1));
        jphy_jb1=new JButton("我的好友");
        jphy_jb2=new JButton("陌生人");
        jphy_jb2.addActionListener(this);
        jphy_jb3=new JButton("黑名单");
        //把两个按钮加到jphy3中
        jphy3.add(jphy_jb2);
        jphy3.add(jphy_jb3);
        jsp1=new JScrollPane(jphy2);
        jphy1.add(jphy_jb1,"North");
        jphy1.add(jsp1,"Center");
        jphy1.add(jphy3,"South");
        //处理第二张卡片(陌生人)
        jpmsr1=new JPanel(new BorderLayout());
        jpmsr2=new JPanel(new GridLayout(20,1,4,4));
        jbls2=new JLabel[20];
        for(int i=0;i<jbls2.length;i++)
        {
            jbls2[i]=new JLabel(i+1+"",new ImageIcon("image/mm.jpg"),JLabel.LEFT);
            jbls2[i].addMouseListener(this);//监听每一个黑名单
//            jbls2[i].setEnabled(false);//把其它人物设置成不线状态
//            if(jbls2[i].getText().equals(ownerId))//把自己设置成在线状态
//            {
//                jbls2[i].setEnabled(true);
//            }
            jpmsr2.add(jbls2[i]);
        }
        jpmsr3=new JPanel(new GridLayout(2,1));
        jpmsr_jb1=new JButton("我的好友");
        jpmsr_jb1.addActionListener(this);
        jpmsr_jb2=new JButton("陌生人");
        jpmsr_jb3=new JButton("黑名单");
        //把两个按钮加到jpmsr3中
        jpmsr3.add(jpmsr_jb1);
        jpmsr3.add(jpmsr_jb2);
        jsp2=new JScrollPane(jpmsr2);
        jpmsr1.add(jpmsr3,"North");
        jpmsr1.add(jsp2,"Center");
        jpmsr1.add(jpmsr_jb3,"South");
        cl=new CardLayout();
        this.setLayout(cl);
        this.add(jphy1,"1");
        this.add(jpmsr1,"2");
        this.setSize(200,400);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle(ownerId+" 好友列表");//窗口显示自己的编号
        this.setVisible(true);
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        //如果点击了陌生人按钮,就显示第二张卡片
        if(e.getSource()==jphy_jb2)
        {
            cl.show(this.getContentPane(),"2");
        }
        else if(e.getSource()==jpmsr_jb1)
        {
            cl.show(this.getContentPane(),"1");
        }
    }
    @Override
    public void mouseClicked(MouseEvent e) {
        //响应用户双击事件,并得到好友的编号
        if(e.getClickCount()==2)//双击
        {
            //得到该好友的编号
            String friendNo=((JLabel)e.getSource()).getText();
            //System.out.println("你希望和"+friendNo+"聊天");
            QqChat qqChat=new QqChat(owner,friendNo);
            //启动线程
            //Thread t=new Thread(qqChat);
            //t.start();
            //把聊天界面加入到管理类中
            ManageQqChat.addQqChat(this.owner+" "+friendNo, qqChat);
        }
    }
    @Override
    public void mouseEntered(MouseEvent e) {
        //
        JLabel jl=(JLabel)e.getSource();
        jl.setForeground(Color.red);
    }
    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub
        JLabel jl=(JLabel)e.getSource();
        jl.setForeground(Color.black);
    }
    @Override
    public void mousePressed(MouseEvent e) {
        // TODO Auto-generated method stub
    }
    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub
    }
}

客户端_QqServer/com.qq.client.model/QqClientConServer.java

/**
 * 这是客户端连接服务器的后台
 */
package com.qq.cllient.model;
import java.util.*;
import java.net.*;
import java.io.*;
import com.qq.client.tools.*;
import com.qq.common.*;;
public class QqClientConServer {
    public Socket s;
    //发送第一次请求
    public boolean sendInfoToServer(Object o)
    {
        boolean b=false;
        try {
            //System.out.println("kk");
            s=new Socket("127.0.0.1",9999);
            ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
            oos.writeObject(o);
            ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
            Message ms=(Message)ois.readObject();
            //这里就是验证用户登录的地方
            if(ms.getMesType().equals("1"))
            {
                //就创建一个该qq号和服务器端保持通讯连接的线程
                ClientConServerThread ccst=new ClientConServerThread(s);
                //启动该通讯线程
                ccst.start();
                ManageClientConServerThread.addClientConServerThread(((User)o).getUserId(), ccst);
                b=true;
            }else{
                //关闭socket
                s.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
        }
        return b;
    }
    //发送信息
    public void SendInfoToServer(Object o)
    {
        try {
            Socket s=new Socket("127.0.0.1",9999);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
        }
    }
}

客户端_QqServer/com.qq.client.model/QqClientUser.java

/**
 * 在model层中的 登录验证
 */
package com.qq.cllient.model;
import java.net.*;
import java.io.*;
import com.qq.common.*;
public class QqClientUser {
    public boolean checkUser(User u)
    {
        return new QqClientConServer().sendInfoToServer(u);
    }
}

客户端_QqServer/com.qq.client.tools/ManageQqChat.java

/**
 * 这是一个管理用户聊天界面的类
 */
package com.qq.client.tools;
import java.util.*;
import com.qq.client.view.*;
public class ManageQqChat {
    private static HashMap hm=new HashMap<String,QqChat>();
    //加入HashMap
    public static void addQqChat(String loginIdAndFriendId,QqChat qqChat)
    {
        hm.put(loginIdAndFriendId, qqChat);
    }
    //从HashMap取出
    public static QqChat getQqChat(String loginIdAndFriendId)
    {
        return (QqChat)hm.get(loginIdAndFriendId);
    }
}

客户端_QqServer/com.qq.client.tools/ManageQqFriendList.java

/**
 * 管理好友、陌生人、黑名单...界面类
 */
package com.qq.client.tools;
import java.util.*;
import java.io.*;
import com.qq.client.view.*;
public class ManageQqFriendList {
    private static HashMap hm=new HashMap<String,QqFriendList>();
    public static void addQqFrendList(String qqid,QqFriendList qqFriendList)
    {
        hm.put(qqid, qqFriendList);
    }
    public static QqFriendList getQqFriendList(String qqId)
    {
        return (QqFriendList)hm.get(qqId);
    }
}

客户端_QqServer/com.qq.client.tools/ClientConServerThread.java

/**
 * 这是客户端和服务器端保持通讯的线程
 */
package com.qq.client.tools;
import java.io.*;
import java.net.*;
import com.qq.client.view.*;
import com.qq.common.Message;
import com.qq.common.MessageType;
public class ClientConServerThread extends Thread{
    private Socket s;
    public Socket getS() {
        return s;
    }
    public void setS(Socket s) {
        this.s = s;
    }
    //构造函数
    public ClientConServerThread(Socket s)
    {
        this.s=s;
    }
    public void run()
    {
        while(true)
        {
            //不停的读取从服务器端发来的消息
            try {
                ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
                Message m=(Message)ois.readObject();
//                System.out.println("读取到从服务器发来的消息"+m.getSender()+" 给"+
//                        m.getGetter()+" 内容:"+m.getCon());
                //如果是普通包
                if(m.getMesType().equals(MessageType.message_comm_mes))
                {
                    //把从服务器获得的消息,显示到该显示的聊天界面
                    QqChat qqChat=ManageQqChat.getQqChat(m.getGetter()+" "+m.getSender());
                    //显示
                    qqChat.showMessage(m);
                }
                //如果返回的是好友上线的包
                else if(m.getMesType().equals(MessageType.message_ret_onLineFriend))
                {
                    //System.out.println("客户端接收到:"+m.getCon());
                    String con=m.getCon();
                    String friends[]=con.split(" ");
                    String getter=m.getGetter();
                    //System.out.println("getter="+getter);
                    //修改相应的好友列表.
                    QqFriendList qqFriendList=ManageQqFriendList.getQqFriendList(getter);
                    if(qqFriendList!=null)
                    {
                        //更新在线好友
                        qqFriendList.updateFriend(m);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

客户端_QqServer/com.qq.client.tools/ManageClientConServerThread.java

/**
 * 这是一个管理客户端和服务器保持通讯的线程类
 */
package com.qq.client.tools;
import java.util.*;
public class ManageClientConServerThread {
    private static HashMap<String,ClientConServerThread> hm=new HashMap<String,ClientConServerThread>();
    //把创建好的ClientConServerThread放入到hm
    public static void addClientConServerThread(String qqId,ClientConServerThread ccst)
    {
        hm.put(qqId, ccst);
    }
    //可以通过qqId取得该线程
    public static ClientConServerThread getClientConServerThread(String qqId)
    {
        return (ClientConServerThread)hm.get(qqId);
    }
}

客户端_QqServer/com.qq.client.common/Message.java

/**
 * 对Message规定一些规则
 * mesType 1->表示是登陆成功
 * mesType 2->表示是登陆失败
 * mesType 3->表示是普通的消息包
 */
package com.qq.common;
public class Message implements java.io.Serializable{
    private String mesType;
    private String sender;
    private String getter;
    private String con;
    private String sendTime;
    public String getSender() {
        return sender;
    }
    public void setSender(String sender) {
        this.sender = sender;
    }
    public String getGetter() {
        return getter;
    }
    public void setGetter(String getter) {
        this.getter = getter;
    }
    public String getCon() {
        return con;
    }
    public void setCon(String con) {
        this.con = con;
    }
    public String getSendTime() {
        return sendTime;
    }
    public void setSendTime(String sendTime) {
        this.sendTime = sendTime;
    }
    public String getMesType() {
        return mesType;
    }
    public void setMesType(String mesType) {
        this.mesType = mesType;
    }
}

客户端_QqServer/com.qq.client.common/MessageType.java

/**
 * 定义消息包的种类
 */
package com.qq.common;
public interface MessageType {
    String message_succeed="1";//登录成功
    String message_login_fail="2";//登录失败
    String message_comm_mes="3";//普通信息包
    String message_get_onLineFriend="4";//请求在线好友的信息包
    String message_ret_onLineFriend="5";//返回在线好友的信息包
}

客户端_QqServer/com.qq.client.common/User.java

/**
 * 这是用户信息类
 */
package com.qq.common;
public class User implements java.io.Serializable{
    //将这个类序列化,就使其对应的对象可以在网络上或者是在文件中传输
    private String userId;
    private String passWd;
    public String getUserId() {
        return userId;
    }
    public void setUserId(String userId) {
        this.userId = userId;
    }
    public String getPassWd() {
        return passWd;
    }
    public void setPassWd(String passWd) {
        this.passWd = passWd;
    }
}

版权所有,转载请注明出处 luowei.github.io.