网络多线程开发小项目--QQ登陆聊天功能(服务端推送新闻、离线留言和文件)

发布时间:2024年01月12日

9.1.5、QQ登陆聊天功能(服务端推送新闻、离线留言和文件)

9.1.5.1、服务端推送新闻
1、需求分析
在这里插入图片描述
2、思路分析
在这里插入图片描述

3、代码实现
QQServer:
1)cn.com.agree.qqserver.service.SendNewsToAllClient

package cn.com.agree.qqserver.service;

import cn.com.agree.qqcommon.Message;
import cn.com.agree.qqcommon.MessageType;
import cn.com.agree.stream.MyObjectOutputStream;
import cn.com.agree.util.Utility;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;

/**
 * @version 1.0
 * @ClassName SendNewsToAll
 * @Description TODO 类描述
 * @date 2024/1/12  11:37 上午
 **/
@Slf4j
public class SendNewsToAllClient implements Runnable {


    @Override
    public void run() {
        while (true) {
            //构建消息对象
            Message message = new Message();
            message.setSender("服务器");
            message.setMsgType(MessageType.MESSAGE_ONLINEAll_MS);
            Scanner scanner = new Scanner(System.in);
            log.debug("请输入要推送的服务器消息(输入exit退出):");
            String news = scanner.next();
            if("exit".equals(news)){
                log.debug("服务器推送线程已退出");
                break;
            }
            message.setContent(news);
            message.setSendTime(new Date().toString());

            log.debug(message.getSender()+" 对大家说: "+message.getContent());
            //遍历服务端所有的用户id得到对应的线程socket转发给对应的客户端
            Map<String, ServerConnectClient> hm = ManageServerConnectClient.getHm();
            Iterator<String> iterator = hm.keySet().iterator();
            while (iterator.hasNext()) {
                String userId = iterator.next().toString();
                try {
                    ObjectOutputStream oos = new MyObjectOutputStream(ManageServerConnectClient.getServerConnectClient(userId).getSocket().getOutputStream());
                    oos.writeObject(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }
    }
}

2)cn.com.agree.qqserver.service.qqServer

 while (true) {
     socket = serverSocket.accept();
     //获取来自客户端发送过来到用户对象
     log.debug("socket Client连接成功");
     new Thread(new SendNewsToAllClient()).start();
     ObjectInputStream bis = new MyObjectInputStream(socket.getInputStream());
     User user = (User) bis.readObject();
     //获取输出流对象写入返回给客户端的消息
     ObjectOutputStream oos = new MyObjectOutputStream(socket.getOutputStream());
     og.debug("user:{}",user);
     Message message = new Message();
     ...
}

4、运行效果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

9.1.5.2、离线留言和文件

1、需求分析
在这里插入图片描述
2、思路分析
在这里插入图片描述
3.1、代码实现(发送离线消息)
1)cn.com.agree.qqserver.service.ManageServerConnectClient

 private static  Map<String, List<Message>> notOnlineMessages = new ConcurrentHashMap<>();
 public static  void addNotOnlineMessage(String getterId, List<Message> messages){
        notOnlineMessages.put(getterId, messages);
 }
 public static List<Message> getNotOnlineMessage(String getterId) {
        return notOnlineMessages.get(getterId);
    }

2)cn.com.agree.qqserver.service.ServerConnectClient

case MessageType.MESSAGE_COMM_MS:

     log.debug("message:{}", message);
     log.debug(message.getSender() + " 对 " + message.getGetter() + " 说: " + message.getContent());
     ServerConnectClient connectClient = ManageServerConnectClient.getServerConnectClient(message.getGetter());
     if(connectClient==null){
     //做离线消息处理,将数据保存到数据库(这里保存到Map中)
     if(ManageServerConnectClient.getNotOnlineMessage(message.getGetter())==null){
        List<Message> messages = new ArrayList<>();
        messages.add(message);                    
        ManageServerConnectClient.addNotOnlineMessage(message.getGetter(),messages);
      }else{                      
        ManageServerConnectClient.getNotOnlineMessage(message.getGetter()).add(message);
      }

     }else {
          //转发消息
        ObjectOutputStream oos2 = new MyObjectOutputStream(connectClient.getSocket().getOutputStream());
        oos2.writeObject(message);//如果用户不在线,可以保存到数据库做离线转发
      }
      break;

3) cn.com.agree.qqserver.service.qqServer

 //去服务端查询是否有来自他的消息,有的话转发给对应的用户
 List<Message> notOnlineMessage = ManageServerConnectClient.getNotOnlineMessage(user.getUserId());
 if(notOnlineMessage!=null&&notOnlineMessage.size()>0){
    for (Message message1 : notOnlineMessage) {
        ObjectOutputStream oos2 = new MyObjectOutputStream(socket.getOutputStream());
        oos2.writeObject(message1);
     }
 }

4.1、效果演示
在这里插入图片描述
在这里插入图片描述
上线后收到消息
在这里插入图片描述
3.2、代码实现(发送离线文件)

 case MessageType.MESSAGE_FILE_MESSAGE:
     //log.debug("message:{}", message);
     log.debug(message.getSender()+" 给 "+message.getGetter()+" 发送了 "+message.getSrc()+" 到我的电脑的 "+message.getDesc()+" 路径");
     ServerConnectClient serverConnectClient = ManageServerConnectClient.getServerConnectClient(message.getGetter());
     if(serverConnectClient==null){
     //做离线消息处理,将数据保存到数据库(这里保存到Map中)
     if(ManageServerConnectClient.getNotOnlineMessage(message.getGetter())==null){
        List<Message> messages = new ArrayList<>();
        messages.add(message);
        ManageServerConnectClient.addNotOnlineMessage(message.getGetter(),messages);
     }else{
        ManageServerConnectClient.getNotOnlineMessage(message.getGetter()).add(message);
      }
    }else {
       //进行转发给客户端
       ObjectOutputStream oos4= new MyObjectOutputStream(serverConnectClient.socket.getOutputStream());
       oos4.writeObject(message);
     }
     break;                        

4.2、效果展示
在这里插入图片描述
在这里插入图片描述
300上线后成功接收
在这里插入图片描述

文章来源:https://blog.csdn.net/adzn1/article/details/135546690
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。