设计C/S架构的IM通信软件(3)

在之前的功能基础上,可以区分开群聊和私聊

引入哈希表来实现,具体代码如下:

客户端类:

复制代码
public class MClient {
    //创建客户端 Socket 再获取输入输出流 启动线程不实时读取服务器发来的消息 String msg 再写一个发送消息 Scanner scan
    //写发送消息的方法 sendMsg (os) 写读取指定长度数据 readMsg()用到保存消息的缓冲区 byte[]
    public static void main(String[] args) throws IOException {
        new MClient().StartMClient();
    }
    public OutputStream os;
    public InputStream is;
    public void StartMClient() throws IOException {
        //创建客户端
        Socket socket = new Socket("127.0.0.1",9999);
        //获取输入输出流
        is = socket.getInputStream();
        os = socket.getOutputStream();
        //启动线程时不实时读取消息
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    String msg = null;
                    try {
                        msg = readMsg();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println(msg);
                }
            }
        }).start();
        //发送消息
        while(true){
            Scanner scan = new Scanner(System.in);//从键盘获得输入
            String line = scan.nextLine();
            sendMsg(line);
        }
    }
    //读取消息
    public String readMsg() throws IOException {
        byte[] b = new byte[1024];
        is.read(b);
        String msg = new String(b);
        return msg.trim();
    }
    //发送消息
    public void sendMsg(String msg) throws IOException {
        String str = msg + "\r\n";
        os.write(str.getBytes());
        os.flush();
    }
}

服务器端:

复制代码
public class MServer {
    public static void main(String[] args) throws IOException {
        new MServer().StartMServer();
    }
    public void StartMServer() throws IOException {
        //创建一个服务器 用哈希表Map<Integer,Socket> map存用户客户端 给用户端设一个ID用来
        //连接客户端server.accept 并放到哈希表 启动线程 保持通信状态
        ServerSocket server = new ServerSocket(9999);
        Map<Integer, Socket> map = new HashMap<>();
        int UserID = 1;
        while(true){
            //连接客户端 把客户端添加到map中
            Socket socket = server.accept();
            map.put(UserID,socket);
            //启动线程 保持通信
            ServerThread serverThread = new ServerThread(socket,map,UserID++);
            new Thread(serverThread).start();
        }
    }
}

线程通信类:

复制代码
public class ServerThread implements Runnable {
    public Socket socket;
    public OutputStream os;
    public InputStream is;
    public Map<Integer,Socket> map;
    public int UserID;
    public ServerThread(Socket socket,Map<Integer,Socket> map,int UserID){
        this.socket = socket;
        this.map = map;
        this.UserID = UserID;
        try {
            os = socket.getOutputStream();
            is = socket.getInputStream();
            sendMsg(UserID,os,"客户端连接成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void run() {
        //读取msg 再去分析msg是广播还是私聊对msg进行分割
        while(true){
            try {
                String msg = readMsg();
                String[] msgArr = msg.split(":");
                if(msgArr[0].equals("g")){
                    //群发
                    for(Map.Entry<Integer,Socket> entry : map.entrySet()){
                        Socket s = entry.getValue();
                        if(s != socket){
                            OutputStream output = s.getOutputStream();
                            sendMsg(UserID,output,msg);
                        }
                    }
                }else{
                    //私聊
                    Integer id = Integer.parseInt(msgArr[0]);
                    //根据id找到对象
                    Socket s = map.get(id);
                    OutputStream output = s.getOutputStream();
                    sendMsg(UserID,output,msgArr[1]);
                }
                System.out.println("client : " + msg);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    //读取消息
    public String readMsg() throws IOException {
        byte[] b = new byte[1024];
        is.read(b);
        String msg = new String(b);
        return msg.trim();
    }
    //发送消息
    public void sendMsg(int UserId,OutputStream os,String msg) throws IOException {
        String str =UserId + ":" + " " + msg + "\r\n";
        os.write(str.getBytes());
        os.flush();
    }
}
相关推荐
zz34572981132 小时前
C语言基础概念7
c语言·开发语言
岁岁种桃花儿2 小时前
深度解析DolphinScheduler核心架构:去中心化调度的设计与实践
架构·去中心化·区块链
咖啡啡不加糖2 小时前
Grafana 监控服务指标使用指南:打造可视化监控体系
java·后端·grafana
€8112 小时前
Java入门级教程26——序列化和反序列化,Redis存储Java对象、查询数据库与实现多消费者消息队列
java·拦截器·序列化和反序列化·数据库查询·redis存储java对象·多消费者消息队列
多多*2 小时前
Mysql数据库相关 事务 MVCC与锁的爱恨情仇 锁的层次架构 InnoDB锁分析
java·数据库·windows·sql·oracle·面试·哈希算法
hellojackjiang20112 小时前
如何保障分布式IM聊天系统的消息可靠性(即消息不丢)
分布式·网络安全·架构·信息与通信
彷徨的蜗牛2 小时前
架构思维的精髓:在解构与集成间驱动数字化演进
架构
二年级程序员2 小时前
C 语言文件操作
c语言
小莞尔2 小时前
【51单片机】【protues仿真】 基于51单片机波形发生器系统
c语言·单片机·嵌入式硬件·物联网·51单片机