|
@@ -13,10 +13,7 @@ import java.nio.channels.SelectableChannel;
|
|
|
import java.nio.channels.SelectionKey;
|
|
import java.nio.channels.SelectionKey;
|
|
|
import java.nio.channels.Selector;
|
|
import java.nio.channels.Selector;
|
|
|
import java.nio.channels.SocketChannel;
|
|
import java.nio.channels.SocketChannel;
|
|
|
-import java.util.HashMap;
|
|
|
|
|
-import java.util.Map;
|
|
|
|
|
-import java.util.Objects;
|
|
|
|
|
-import java.util.Set;
|
|
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* @ProjectName: chat-gwng
|
|
* @ProjectName: chat-gwng
|
|
@@ -32,6 +29,8 @@ public class ReadHandler implements Runnable, Closeable {
|
|
|
private Map<String,SocketChannel> userChannels = new HashMap<>();
|
|
private Map<String,SocketChannel> userChannels = new HashMap<>();
|
|
|
private boolean isExit = false;
|
|
private boolean isExit = false;
|
|
|
private ServerController serverController;
|
|
private ServerController serverController;
|
|
|
|
|
+ //ip:port的格式
|
|
|
|
|
+ private HashSet<String> udpAddressSet = new HashSet<>();
|
|
|
|
|
|
|
|
public ReadHandler(Selector readSelector,ServerController serverController) {
|
|
public ReadHandler(Selector readSelector,ServerController serverController) {
|
|
|
this.readSelector = readSelector;
|
|
this.readSelector = readSelector;
|
|
@@ -66,7 +65,7 @@ public class ReadHandler implements Runnable, Closeable {
|
|
|
if (select > 0) {
|
|
if (select > 0) {
|
|
|
Set<SelectionKey> selectionKeys = readSelector.selectedKeys();
|
|
Set<SelectionKey> selectionKeys = readSelector.selectedKeys();
|
|
|
for (SelectionKey selectionKey : selectionKeys) {
|
|
for (SelectionKey selectionKey : selectionKeys) {
|
|
|
- if (selectionKey.isReadable() && selectionKey.isValid()) {
|
|
|
|
|
|
|
+ if (selectionKey.isValid() && selectionKey.isReadable()) {
|
|
|
//拿到channel
|
|
//拿到channel
|
|
|
SelectableChannel channel = selectionKey.channel();
|
|
SelectableChannel channel = selectionKey.channel();
|
|
|
SocketChannel socketChannel = (SocketChannel) channel;
|
|
SocketChannel socketChannel = (SocketChannel) channel;
|
|
@@ -81,6 +80,7 @@ public class ReadHandler implements Runnable, Closeable {
|
|
|
byteBuffer = ByteBuffer.allocate(size);
|
|
byteBuffer = ByteBuffer.allocate(size);
|
|
|
len = socketChannel.read(byteBuffer);
|
|
len = socketChannel.read(byteBuffer);
|
|
|
Message message = Encoder.decode(byteBuffer);
|
|
Message message = Encoder.decode(byteBuffer);
|
|
|
|
|
+ System.out.println("message = " + message);
|
|
|
//信息处理
|
|
//信息处理
|
|
|
if (message.getType() == Message.MessageType.USER) {
|
|
if (message.getType() == Message.MessageType.USER) {
|
|
|
//用户信息
|
|
//用户信息
|
|
@@ -88,18 +88,20 @@ public class ReadHandler implements Runnable, Closeable {
|
|
|
switch (messageTarget){
|
|
switch (messageTarget){
|
|
|
case Message.MessageTarget.SERVER:
|
|
case Message.MessageTarget.SERVER:
|
|
|
//发送给系统的信息
|
|
//发送给系统的信息
|
|
|
- //todo
|
|
|
|
|
|
|
+ System.out.println("系统信息");
|
|
|
break;
|
|
break;
|
|
|
case Message.MessageTarget.GROUP:
|
|
case Message.MessageTarget.GROUP:
|
|
|
//群聊
|
|
//群聊
|
|
|
//转发信息
|
|
//转发信息
|
|
|
|
|
+ System.out.println("群聊信息");
|
|
|
chatWithGroupHandler(message,socketChannel);
|
|
chatWithGroupHandler(message,socketChannel);
|
|
|
break;
|
|
break;
|
|
|
case Message.MessageTarget.CLIENT:
|
|
case Message.MessageTarget.CLIENT:
|
|
|
- //todo
|
|
|
|
|
|
|
+ System.out.println("客户端信息");
|
|
|
break;
|
|
break;
|
|
|
default:
|
|
default:
|
|
|
//私聊信息
|
|
//私聊信息
|
|
|
|
|
+ System.out.println("私聊信息");
|
|
|
chatWithPrivateHandler(message);
|
|
chatWithPrivateHandler(message);
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
@@ -108,12 +110,22 @@ public class ReadHandler implements Runnable, Closeable {
|
|
|
switch (message.getOperate()){
|
|
switch (message.getOperate()){
|
|
|
case Message.OperateType.LOGIN:
|
|
case Message.OperateType.LOGIN:
|
|
|
//登录
|
|
//登录
|
|
|
|
|
+ System.out.println("登陆");
|
|
|
loginHandler(message,selectionKey,socketChannel);
|
|
loginHandler(message,selectionKey,socketChannel);
|
|
|
break;
|
|
break;
|
|
|
case Message.OperateType.LOGOUT:
|
|
case Message.OperateType.LOGOUT:
|
|
|
//登出
|
|
//登出
|
|
|
|
|
+ System.out.println("登出");
|
|
|
userLogoutHandler(message,selectionKey, socketChannel);
|
|
userLogoutHandler(message,selectionKey, socketChannel);
|
|
|
break;
|
|
break;
|
|
|
|
|
+ case Message.OperateType.UDP:
|
|
|
|
|
+ //上报的UDP地址
|
|
|
|
|
+ UDPAddressHandler(message);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case Message.OperateType.REVOKE:
|
|
|
|
|
+ //撤回信息
|
|
|
|
|
+ writeHandler.sendMessageWithGroup(message,socketChannel);
|
|
|
|
|
+ break;
|
|
|
default:
|
|
default:
|
|
|
System.err.println("未知操作");
|
|
System.err.println("未知操作");
|
|
|
System.err.println(message);
|
|
System.err.println(message);
|
|
@@ -124,9 +136,8 @@ public class ReadHandler implements Runnable, Closeable {
|
|
|
//连接意外中断导致异常
|
|
//连接意外中断导致异常
|
|
|
Object attachment = selectionKey.attachment();
|
|
Object attachment = selectionKey.attachment();
|
|
|
String username = (String) attachment;
|
|
String username = (String) attachment;
|
|
|
- //todo
|
|
|
|
|
- System.out.println(username+"掉线了");
|
|
|
|
|
- Message message = new Message(username+"掉线了");
|
|
|
|
|
|
|
+ Message message = Message.createSystemBroadcastMessage(username+"掉线了");
|
|
|
|
|
+ chatWithGroupHandler(message,socketChannel);
|
|
|
//更新UI
|
|
//更新UI
|
|
|
serverController.addMessage(message);
|
|
serverController.addMessage(message);
|
|
|
serverController.removeUser(username);
|
|
serverController.removeUser(username);
|
|
@@ -156,21 +167,21 @@ public class ReadHandler implements Runnable, Closeable {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private void UDPAddressHandler(Message message) {
|
|
|
|
|
+ String content = message.getContent();
|
|
|
|
|
+ if (!udpAddressSet.contains(content))
|
|
|
|
|
+ udpAddressSet.add(content);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private void loginHandler(Message message,SelectionKey selectionKey,SocketChannel socketChannel) {
|
|
private void loginHandler(Message message,SelectionKey selectionKey,SocketChannel socketChannel) {
|
|
|
String username = message.getSource();
|
|
String username = message.getSource();
|
|
|
- if (userChannels.containsKey(username) && Message.MessageTarget.SERVER.equals(username)) {
|
|
|
|
|
|
|
+ System.out.println(message);
|
|
|
|
|
+ if (userChannels.containsKey(username) || Message.MessageTarget.SERVER.equals(username)) {
|
|
|
//用户名重复
|
|
//用户名重复
|
|
|
message = Message.createSystemMessage("用户名重复:'%s'".formatted(username), Message.OperateType.LOGIN, Message.MessageTarget.SERVER, Message.MessageTarget.CLIENT);
|
|
message = Message.createSystemMessage("用户名重复:'%s'".formatted(username), Message.OperateType.LOGIN, Message.MessageTarget.SERVER, Message.MessageTarget.CLIENT);
|
|
|
writeHandler.sendMessageWithPrivate(message, socketChannel);
|
|
writeHandler.sendMessageWithPrivate(message, socketChannel);
|
|
|
|
|
+ //重新登陆
|
|
|
serverController.addMessage(message);
|
|
serverController.addMessage(message);
|
|
|
- //释放资源
|
|
|
|
|
- selectionKey.cancel();
|
|
|
|
|
- try {
|
|
|
|
|
- if (Objects.nonNull(socketChannel) && socketChannel.isOpen())
|
|
|
|
|
- socketChannel.close();
|
|
|
|
|
- } catch (IOException e) {
|
|
|
|
|
- e.printStackTrace();
|
|
|
|
|
- }
|
|
|
|
|
}else{
|
|
}else{
|
|
|
//用户名保存到对应的selectionKey上,之后需要可以从里面取出
|
|
//用户名保存到对应的selectionKey上,之后需要可以从里面取出
|
|
|
selectionKey.attach(username);
|
|
selectionKey.attach(username);
|
|
@@ -185,7 +196,7 @@ public class ReadHandler implements Runnable, Closeable {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void chatWithPrivateHandler(Message message) {
|
|
private void chatWithPrivateHandler(Message message) {
|
|
|
- String username = message.getSource();
|
|
|
|
|
|
|
+ String username = message.getTarget();
|
|
|
SocketChannel socketChannel = userChannels.getOrDefault(username, null);
|
|
SocketChannel socketChannel = userChannels.getOrDefault(username, null);
|
|
|
if (Objects.nonNull(socketChannel)) {
|
|
if (Objects.nonNull(socketChannel)) {
|
|
|
writeHandler.sendMessageWithPrivate(message, socketChannel);
|
|
writeHandler.sendMessageWithPrivate(message, socketChannel);
|
|
@@ -202,10 +213,7 @@ public class ReadHandler implements Runnable, Closeable {
|
|
|
if(userChannels.containsKey(username))
|
|
if(userChannels.containsKey(username))
|
|
|
userChannels.remove(username);
|
|
userChannels.remove(username);
|
|
|
//广播用户下线
|
|
//广播用户下线
|
|
|
- message = new Message();
|
|
|
|
|
- message.setSource(Message.MessageTarget.SERVER);
|
|
|
|
|
- message.setTarget(Message.MessageTarget.GROUP);
|
|
|
|
|
- message.setContent(username+"下线了");
|
|
|
|
|
|
|
+ message = Message.createSystemBroadcastMessage(username+"下线了");
|
|
|
writeHandler.sendMessageWithGroup(message, socketChannel);
|
|
writeHandler.sendMessageWithGroup(message, socketChannel);
|
|
|
//更新UI
|
|
//更新UI
|
|
|
serverController.addMessage(message);
|
|
serverController.addMessage(message);
|