Socket.D v2.5.11

实战 - 简单的聊天实现

</> markdown

简单的聊天实现(聊天室 + 上下线 + 管理)

1、服务端

public class Demo06_Im_Server {
   static Map<String, Session> userList = new HashMap<>();
    public static void main(String[] args) throws Exception {
        SocketD.createServer("sd:udp")
                .config(c -> c.port(8602))
                .listen(new PathListener()
                        //::::::::::用户频道处理
                        .doOf("/", new EventListener()
                                .doOnOpen(s -> {
                                    //用户连接
                                    String user = s.param("u");
                                    if (StrUtils.isNotEmpty(user)) {
                                        //有用户名,才登录成功
                                        userList.put(s.sessionId(), s);
                                        s.attrPut("user", user);
                                    } else {
                                        //否则说明是非法的
                                        s.close();
                                    }
                                }).doOnClose(s -> {
                                    userList.remove(s.sessionId());

                                    String room = s.attr("room");

                                    if (StrUtils.isNotEmpty(room)) {
                                        pushToRoom(room, new StringEntity("有人退出聊天室:" + s.attr("user")));
                                    }
                                }).doOn("cmd.join", (s, m) -> {
                                    //::加入房间指令
                                    String room = m.meta("room");

                                    if (StrUtils.isNotEmpty(room)) {
                                        s.attrPut("room", room);

                                        pushToRoom(room, new StringEntity("新人加入聊天室:" + s.attr("user")));
                                    }
                                }).doOn("cmd.chat", (s, m) -> {
                                    //::聊天指令
                                    String room = m.meta("room");

                                    if (StrUtils.isNotEmpty(room)) {
                                        StringBuilder buf = new StringBuilder();
                                        buf.append(m.meta("sender")).append(": ").append(m.dataAsString());

                                        pushToRoom(room, new StringEntity(buf.toString()));
                                    }
                                }))
                        //::::::::::管理频道处理
                        .doOf("/admin", new EventListener()
                                .doOnOpen((session) -> {
                                    //管理员签权
                                    String user = session.param("u");
                                    String token = session.param("t");

                                    if ("admin".equals(user) && "admin".equals(token)) {

                                    } else {
                                        session.close();
                                    }
                                }).doOn("cmd.t", (s, m) -> {
                                    String user = m.meta("u");
                                    String room = m.meta("room");

                                    Session s2 = userList.values().parallelStream().filter(s1 -> user.equals(s1.attr("user"))).findFirst().get();
                                    if (s2 != null) {
                                        s2.attrPut("room", null);
                                        s2.send("cmd.t", new StringEntity("你被T出聊天室: " + room));
                                    }
                                })
                        )
                ).start();
    }

    static void pushToRoom(String room, Entity message) {
        userList.values().parallelStream().filter(s1 -> room.equals(s1.attr("room")))
                .forEach(s1 -> {
                    RunUtils.runAndTry(() -> {
                        s1.send("cmd.chat", message); //给房间的每个人转发消息
                    });
                });
    }
}

2、客户端

public class Demo06_Im_Client {
    private static String ADMIN_TOKEN = "admin";// 方便demo测试输入

    private static BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
    private static String user = null;
    private static String token = null;
    private static ClientSession clientSession = null;
    private static String room;

    public static void main(String[] args) throws Exception {
        //登录
        login();

        while (true) {
            //加入聊天室
            joinRoom();

            //聊天开始
            chatStart();
        }
    }

    /**
     * 开始聊天
     * */
    private static void chatStart() throws Exception {
        if (token == null) {
            System.out.println("开始聊天:");

            while (true) {
                String msg = console.readLine();

                if(room == null){
                    System.out.println("被T出聊天室,需要重新选择聊天室!");
                    return;
                }

                clientSession.send("cmd.chat", new StringEntity(msg)
                        .metaPut("room", room)
                        .metaPut("sender", user));
            }
        }
    }

    /**
     * 加入聊天室
     * */
    private static void joinRoom() throws Exception {
        if (token == null) {
            System.out.println("请选择聊天室进入: c1 或 c2");
            room = console.readLine();

            while ("c1".equals(room) == false && "c2".equals(room) == false) {
                System.out.println("错,请重新选择聊天室进入: c1 或 c2");
                room = console.readLine();
            }

            //加入聊天室
            clientSession.send("cmd.join", new StringEntity("").metaPut("room", room));
        }
    }

    /**
     * 登录
     * */
    private static void login() throws Exception {
        System.out.println("输入用户名:");
        user = console.readLine();

        if ("admin".equals(user)) {
            System.out.println("请输入管理令牌:");
            token = console.readLine();

            while (ADMIN_TOKEN.equals(token) == false) {
                System.out.println("错,请重新输入管理令牌:");
                token = console.readLine();
            }
        }

        System.out.println("开始登录服务器...");

        if (token == null) {
            //进入用户频道
            clientSession = SocketD.createClient("sd:udp://127.0.0.1:8602/?u=" + user).listen(new EventListener().doOnMessage((s, m) -> {
                System.err.println("聊到室:" + m.dataAsString());
            }).doOn("cmd.t", (s, m)->{
                //把房间置空
                room = null;
            })).open();
        } else {
            System.out.println("进入管理频道");
            //进入管理频道
            clientSession = SocketD.createClient("sd:udp://127.0.0.1:8602/admin?u=" + user + "&t=" + token).open();
            // 群主上身
            adminStart();
        }

        System.out.println("登录服务器成功!");
    }

    /**
     * 群主上身
     * @throws Exception
     */
    private static void adminStart() throws Exception {
        System.out.println("群管理T人模式:");
        while (true) {
            System.out.println("请输入你想踢的人昵称:");
            String id = console.readLine();

            if(id == null){
                System.err.println("请输入正确的昵称:");
                return;
            }

            clientSession.send("cmd.t", new StringEntity("")
                    .metaPut("room", "当前聊天室")
                    .metaPut("u", id));

            System.err.println("用户已下线:" + id);
        }
    }
}