实战 - 简单的聊天实现
简单的聊天实现(聊天室 + 上下线 + 管理)
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);
}
}
}