韩顺平30天javaQQ通信作业扩展-完成离线提醒及接收接收

我这里只显示需要添加的代码,其余代码与韩老师写的一样。

这里用户1发短信给用户2

大体思路:1.在服务器接收用户1输入信息ObjectInputStream的时候有两个分支(if-else),

第一,如果在线程池里用户2不存在,就把输入信息保存在concurrentHashMap

第二,如果线程池里存在用户2,就把输入信息通过ObjectOutputStream.WriteObject发给客户端。

2.在服务器,用户2发送登录成功MessageType给客户端的时候,同时把用户1的信息也发出去,通过message.setContent()。

建议自己在想一下,因为很简单,具体代码如下:

1.设定属性.private static ConcurrentHashMap>ofLineDb = new ConcurrentHashMap<>();

2.写方法用来保存内容

public static void dbmessage(String userId,Message message1){

        if (!ManageClientThread.getHm().containsKey(userId)){

        ArrayList messages1 = new ArrayList<>();

        messages1.add(message1); ofLineDb.put(userId,messages1);

}

3.服务器对收到的信息进行分流
else if (o1.getMesType().equals(MessageType.MESSAGE_COMM_MES.getNum())){
     //把客户端私聊的内容保存在dbmessage方法里的ConcurrentHashMap里
    if (!ManageClientThread.getHm().containsKey(o1.getGetter())) {
        o1.setContent("\n"+o1.getSender()+"发消息说"+o1.getContent());
        QQserver.dbmessage(o1.getGetter(), o1);

    }
        //传递给客户端,通过需要收到的用户id找到socket
        ServerConnectClientThread getserverconnectclietnthread = ManageClientThread.getserverconnectclietnthread(o1.getGetter());
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(getserverconnectclietnthread.getSocket().getOutputStream());
            objectOutputStream.writeObject(o1);  }

4.在服务器,当用户2登入时,从数组里取出用户1的信息打包过去。

if (ofLineDb.get(o1.getUserId())!=null){
    ArrayList messages = ofLineDb.get(o1.getUserId());
    Iterator iterator = messages.iterator();
    while (iterator.hasNext()) {
        Message next = iterator.next();
        message.setContent(next.getContent());


    }
}

5.客户端里输出

if (ManageClientConnectiServerThread.getccst(message.getGetter())==null){System.out.println(message.getGetter()+"用户已经离线");}else
{ System.out.println(senderId+"对"+getterId+"说"+content);}

服务器端的:


public class ServerConnectClientThread extends Thread{
    private Socket socket;
    private String userId;//连接到服务端的用户id


    public ServerConnectClientThread(Socket socket, String userId) {
        this.socket = socket;
        this.userId = userId;
    }

    @Override
    public void run() {//这里线程处于rum的状态,可以发送/接送消息
        while(true){
            System.out.println("服务端和客户端"+userId+"保持通信,读取数据...");
            try {
                ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
                Object o = objectInputStream.readObject();
                Message o1 = (Message) o;
//                后面会使用message
//                根据message的类型,做相应的业务处理


                if (o1.getMesType().equals(MessageType.MESSAGE_GET_ONLINEFRIEND.getNum())){
                    //客户端要在先用户列表
                    /*
                    在线用户列表形式100 200
                     */
                    System.out.println(o1.getSender()+"要在线用户列表");
                    String onlineUser = ManageClientThread.getOnlineUser();
                    //返回message
                    //构建一个message对象,返回给客户端
                    Message message = new Message();
                    message.setMesType(MessageType.MESSAGE_RET_ONLINEFRIEND.getNum());
                    message.setContent(onlineUser);
                    message.setGetter(message.getSender());
                    //返回给客户端
                    ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
                    objectOutputStream.writeObject(message);
                } else if (o1.getMesType().equals(MessageType.MESSAGE_CLIENT_EXIT.getNum())) {//如果客户端退出把socket退出
                    System.out.println(o1.getSender()+"退出");
                     //将这个客户端对应线程,从集合中删除
                    ManageClientThread.removeServerConnectClientThread(o1.getSender());
                    socket.close();//关闭链接
                    //退出线程
                    break;
                } else if (o1.getMesType().equals(MessageType.MESSAGE_COMM_MES.getNum())){
                     //把客户端私聊的内容保存在dbmessage方法里的ConcurrentHashMap里
                    if (!ManageClientThread.getHm().containsKey(o1.getGetter())) {
                        o1.setContent("\n"+o1.getSender()+"发消息说"+o1.getContent());
                        QQserver.dbmessage(o1.getGetter(), o1);




                    }else {
                        //传递给需要收到的用户id


                        ServerConnectClientThread getserverconnectclietnthread = ManageClientThread.getserverconnectclietnthread(o1.getGetter());
                            ObjectOutputStream objectOutputStream = new ObjectOutputStream(getserverconnectclietnthread.getSocket().getOutputStream());
                            objectOutputStream.writeObject(o1);


                    }

                    //如果,提示客户不在线,通过保存到数据库达到离线留言
                }else if (o1.getMesType().equals(MessageType.MESSAGE_TO_ALL_MES.getNum())){

                    HashMap hm = ManageClientThread.getHm();
                    Iterator iterator = hm.keySet().iterator();
                    while (iterator.hasNext()) {
                        String next = iterator.next();
                        //取出在线用户id
                        if (!(next.equals(o1.getSender()))){
                            //进行转发message
                            ObjectOutputStream objectOutputStream =
                                    new ObjectOutputStream(hm.get(next).getSocket().getOutputStream());
                            objectOutputStream.writeObject(o1);
                        }
                    }  hm.remove(o1.getSender());
                }else if (o1.getMesType().equals(MessageType.FILE_TO_ONE_MES.getNum())){
                    ServerConnectClientThread getserverconnectclietnthread =
                            ManageClientThread.getserverconnectclietnthread(o1.getGetter());
                    Socket socket = getserverconnectclietnthread.getSocket();
                    ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
                    objectOutputStream.writeObject(o1);
                }



                else {
                    System.out.println("其他类型的message,暂时不处理");
                }



            } catch (IOException | ClassNotFoundException e) {
                e.printStackTrace();
            }

        }
    }

    public Socket getSocket() {
        return socket;
    }
}

public class QQserver {
    //ConcurrentHashMap,线程安全的HashMap,多线程下是阿暖的
    private ServerSocket ss =null;
    //创建一个集合,存放多个用户,如果是这些用户登入就认为是合法的
    private static HashMap validUsers = new HashMap<>();
    private static ConcurrentHashMap>ofLineDb = new ConcurrentHashMap<>();

    public static ConcurrentHashMap> getOfLineDb() {
        return ofLineDb;
    }

    public static void setOfLineDb(ConcurrentHashMap> ofLineDb) {
        QQserver.ofLineDb = ofLineDb;
    }

    static {//在静态代码块,初始化validUsers
        //

        validUsers.put("100",new User("100","123456"));
        validUsers.put("200",new User("200","123456"));
        validUsers.put("300",new User("300","123456"));
        validUsers.put("至尊宝",new User("至尊宝","123456"));
        validUsers.put("铺地老祖",new User("菩提老祖","123456"));
        }
        public static void dbmessage(String userId,Message message1){
            if (!ManageClientThread.getHm().containsKey(userId)){


                ArrayList messages1 = new ArrayList<>();



                messages1.add(message1);
                ofLineDb.put(userId,messages1);




            }
        }

      private boolean checkUser(String userId,String passwd){

          System.out.println("准备登入");
          User user = validUsers.get(userId);
          if (user==null){//说明userId没有存在validUsers的key中
              return false;
          }if (!user.getPasswd().equals(passwd)){//userId正确,但是密码错误
              return false;
          }

          return true;
      }

    public QQserver()  {
        System.out.println("服务端在9999端口监听。。。");
        try {
            //启动推送新闻的线程
            new Thread(new SendNewsToALLService()).start();
            ss = new ServerSocket(9999);
            while(true) {//监听是循环的一直监听的,当合某个客户端建立链接后,会继续监听,如果没有客户端服务器会阻塞在这里
                //因此while
                Socket accept = ss.accept();//如果没有客户端链接,就会阻塞
                //得到socket关联的对象输入流
                ObjectInputStream objectInputStream = new ObjectInputStream(accept.getInputStream());
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(accept.getOutputStream());
                Object o = objectInputStream.readObject();

                //得到socket冠梁的对象输出流
                User o1 = (User) o;
                //创建一个Message对象,准备回复客户端
                Message message = new Message();
                //验证
                if (checkUser(o1.getUserId(),o1.getPasswd())){//登录通过
                    //登录成功
                    message.setMesType(MessageType.MESSAGE_LOGIN_SUCCEED.getNum());
                    //将Message对象回复
                    //封装私聊内容发送给客户端
                    if (ofLineDb.get(o1.getUserId())!=null){
                        ArrayList messages = ofLineDb.get(o1.getUserId());
                        Iterator iterator = messages.iterator();
                        while (iterator.hasNext()) {
                            Message next = iterator.next();
                            message.setContent(next.getContent());


                        }
                    }
                    objectOutputStream.writeObject(message);

                    //创建一个线程,和客户端进行链接
                    ServerConnectClientThread serverConnectClientThread = new ServerConnectClientThread(accept, o1.getUserId());
                    serverConnectClientThread.start();
                    //把该线程对象,放入到一个集合中,进行管理,
                    //写DB
                    ManageClientThread.addClentThread(o1.getUserId(), serverConnectClientThread);




                }else {
                    //登录失败]
                    System.out.println("用户id="+ o1.getUserId()+"验证失败");
                    message.setMesType(MessageType.MESSAGE_LOGIN_FAIL.getNum());
                    objectOutputStream.writeObject(message);
                    accept.close();
                }

            }

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }finally {
            //如果服务器退出了while,说明服务器端不在监听,因此关闭ServerSocket
            try {
                ss.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

客户端的:


public class MessageClientService {

    /**
     *
     * @param content  内容
     * @param senderId  发送用户id
     * @param getterId  接收用户id
     */
    public static  void sendMessageToOne(String content,String senderId,String getterId){
        //构建message
        Message message = new Message();
        message.setSender(senderId);
        message.setGetter(getterId);
        message.setContent(content);

        message.setMesType(MessageType.MESSAGE_COMM_MES.getNum());//设置消息类型
        message.setSendTime(new Date().toString());//发送时间设置到message对象

        if (ManageClientConnectiServerThread.getccst(message.getGetter())==null){System.out.println(message.getGetter()+"用户已经离线");}else
        { System.out.println(senderId+"对"+getterId+"说"+content);}
        //发送给服务端
        try {
            ClientConnectServerThread getccst = ManageClientConnectiServerThread.getccst(senderId);
            Socket socket = getccst.getSocket();

            ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
           objectOutputStream.writeObject(message);


        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    public static void sendMessageToAll(String content,String senderId){
        Message message = new Message();
        message.setSender(senderId);

        message.setContent(content);
        message.setMesType(MessageType.MESSAGE_TO_ALL_MES.getNum());//设置消息类型群发
        message.setSendTime(new Date().toString());//发送时间设置到message对象
        System.out.println(senderId+"对大家说"+content);

        //发送给服务端
        try {
            ClientConnectServerThread getccst = ManageClientConnectiServerThread.getccst(senderId);
            Socket socket = getccst.getSocket();

            ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            objectOutputStream.writeObject(message);


        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

效果:

登入100,发短信

韩顺平30天javaQQ通信作业扩展-完成离线提醒及接收接收_第1张图片

 登入200发短信韩顺平30天javaQQ通信作业扩展-完成离线提醒及接收接收_第2张图片

 韩顺平30天javaQQ通信作业扩展-完成离线提醒及接收接收_第3张图片

 

你可能感兴趣的:(p2p,html,.net)