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

在之前基础上实现的功能:

1.自定义客户端,让服务器实现多客户端连接

2.服务器广播消息

客户类:

复制代码
public class MClient {
    public static void main(String[] args) {
        try {
            new MClient().StartMClient();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    //创建客户端 获取输入输出流 启动线程不实时 读取服务器发来的消息 还有去发送消息
    public OutputStream os;
    public InputStream is;
    public void StartMClient() throws IOException {
        Socket socket = new Socket("127.0.0.1",9999);
        os = socket.getOutputStream();
        is = socket.getInputStream();
        new Thread(new Runnable() {
            @Override
            public void run() {
                String msg = null;
                try {
                    msg = readMsg();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("Server:"+msg);
            }
        }).start();
        //发送消息
        while(true){
            Scanner scan = new Scanner(System.in);//从键盘获得输入
            String line = scan.nextLine();//当输入回车时 把前面输入的字符保存到字符串
            sendMsg(line);
        }
    }
    //写sendmsg的方法
    public void sendMsg(String msg) throws IOException {
        String str = msg +"\r\n";
        os.write(str.getBytes());
        os.flush();
    }
    //写readmsg的方法
    public String readMsg() throws IOException {
        //保存消息的缓冲区
        byte[] b = new byte[1024];
        //输入流读
        is.read(b);
        //字节换成字符串
        String msg = new String(b);
        //去掉字符串左右的空白部分
        return msg.trim();
    }
}

服务器类:

复制代码
public class MServer {
    public static void main(String[] args) {
        try {
            new MServer().startMServer();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    //创建服务器 用list存客户端 while循环去连接客户端 添加到lists 启动线程保持通信状态
    public void startMServer() throws IOException {
        //创建服务器
        ServerSocket server = new ServerSocket(9999);
        System.out.println("启动服务器....");
        //用来存放socket客户端的list
        ArrayList<Socket> lists = new ArrayList<>();
        while(true){
            //阻塞监听器连接过来的客户端
            Socket socket = server.accept();
            lists.add(socket);
            //启动线程保持通信状态
            ServerThread serverThread = new ServerThread(socket,lists);
            new Thread(serverThread).start();
        }
    }
}

服务器线程类:

复制代码
public class ServerThread implements Runnable{
    //构筑方法先把必要的客户端和lists传入 包括重新得到is os输入输出流
    public Socket socket;
    public InputStream is;
    public OutputStream os;
    public ArrayList<Socket> lists;
    public ServerThread(Socket socket, ArrayList<Socket> lists){
        this.socket = socket;
        this.lists = lists;
        try {
            is = socket.getInputStream();
            os = socket.getOutputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    //用while循环 读取到的msg消息 并把客户端的消息广播给所有在线的人 不发自己
    public void run() {
        try {
            String msg = readMsg();
            for(Socket s:lists){
                if(s != socket){//不发给自己
                    OutputStream output = s.getOutputStream();
                    sendMsg(output,msg);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    //发送消息 sendMsg
    public void sendMsg(OutputStream os, String msg) throws IOException {
        String str = msg + "\r\n";
        os.write(str.getBytes());
        os.flush();
    }
    //读取消息 readMsg
    public String readMsg() throws IOException {
        byte[] b = new byte[1024];
        is.read(b);
        String msg = new String(b);
        return msg.trim();
    }
}
相关推荐
YatHinLay2 分钟前
Spring Boot + Calcite 实现跨库查询
java
酷炫码神25 分钟前
MosMos 创意效果与能力边界展示
java
这个DBA有点耶27 分钟前
InnoDB索引组织表下,复合主键和自增主键的物理存储差异与选型对比
数据库·mysql·架构
Wang's Blog32 分钟前
Java 接入Redis: 使用Jedis操作Redis
java·服务器·redis
事圆则缓35 分钟前
Java 8 Lambda、Stream、Optional 与 Android 边界:从回调语法到运行时兼容
android·java
shehuiyuelaiyuehao43 分钟前
算法50,分治归并,数组中的逆序对
java·算法
烽学长1 小时前
(附源码)基于Springboot+vue的图书阅读分享系统的设计与实现
java·spring boot·后端
Ivanqhz1 小时前
数据搬运是性能关键
java·服务器·网络·人工智能·深度学习
青山木1 小时前
RocketMQ 入门到原理(三):消息存储原理
java·后端·中间件·架构·rocketmq
MayBaymax1 小时前
Spring AI Alibaba Graph 实战:客服工单智能处理
java·ai·ai编程