|
|
@@ -0,0 +1,110 @@
|
|
|
+package space.anyi.chatServer;
|
|
|
+
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.io.Closeable;
|
|
|
+import java.io.IOException;
|
|
|
+import java.net.InetSocketAddress;
|
|
|
+import java.nio.channels.SelectionKey;
|
|
|
+import java.nio.channels.Selector;
|
|
|
+import java.nio.channels.ServerSocketChannel;
|
|
|
+import java.nio.channels.SocketChannel;
|
|
|
+import java.util.Objects;
|
|
|
+import java.util.Set;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @ProjectName: chat-gwng
|
|
|
+ * @FileName: ChatServer
|
|
|
+ * @Author: 杨逸
|
|
|
+ * @Data:2025/9/22 15:45
|
|
|
+ * @Description:
|
|
|
+ */
|
|
|
+@Data
|
|
|
+public class ChatServer implements Runnable, Closeable {
|
|
|
+ private InetSocketAddress inetSocketAddress;
|
|
|
+ private ServerSocketChannel serverSocketChannel;
|
|
|
+ private Selector acceptSelector;
|
|
|
+ private Selector readSelector;
|
|
|
+ private ReadHandler readHandler;
|
|
|
+ private boolean isExit = false;
|
|
|
+
|
|
|
+ public ChatServer(int port) throws IOException {
|
|
|
+ System.out.println("server init");
|
|
|
+ //配置服务监听的端口
|
|
|
+ this.inetSocketAddress = new InetSocketAddress(port);
|
|
|
+ this.serverSocketChannel = ServerSocketChannel.open().bind(inetSocketAddress);
|
|
|
+ this.serverSocketChannel.configureBlocking(false);
|
|
|
+ //创建一个监听连接事件的选择器
|
|
|
+ this.acceptSelector = Selector.open();
|
|
|
+ //创建一个监听读事件的选择器
|
|
|
+ this.readSelector = Selector.open();
|
|
|
+ //自定义读事件处理器,用处理客户端发送的消息
|
|
|
+ this.readHandler = new ReadHandler(readSelector);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ System.out.println("server listen...");
|
|
|
+ try {
|
|
|
+ listen();
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ System.err.println("server bad by error");
|
|
|
+ try {
|
|
|
+ this.close();
|
|
|
+ } catch (IOException ex) {
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void listen() throws IOException {
|
|
|
+ //注册连接事件
|
|
|
+ serverSocketChannel.register(acceptSelector, SelectionKey.OP_ACCEPT);
|
|
|
+ //启动读事件处理器
|
|
|
+ new Thread(readHandler).start();
|
|
|
+ while(true){
|
|
|
+ if (isExit)break;
|
|
|
+ int select = acceptSelector.select(100);
|
|
|
+ if(select > 0){
|
|
|
+ Set<SelectionKey> selectionKeys = acceptSelector.selectedKeys();
|
|
|
+ for (SelectionKey selectionKey : selectionKeys) {
|
|
|
+ if (selectionKey.isAcceptable()) {
|
|
|
+ //有客户端连接
|
|
|
+ SocketChannel socketChannel = serverSocketChannel.accept();
|
|
|
+ System.out.println("client connect");
|
|
|
+ socketChannel.configureBlocking(false);
|
|
|
+ //连接channel注册到读事件处理器
|
|
|
+ socketChannel.register(readSelector,SelectionKey.OP_READ);
|
|
|
+ }
|
|
|
+ //移除selectionKey,防止重复处理
|
|
|
+ selectionKeys.remove(selectionKey);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void close() throws IOException {
|
|
|
+ exit();
|
|
|
+ System.out.println("close chatServer");
|
|
|
+ if (Objects.nonNull(acceptSelector) && acceptSelector.isOpen()) {
|
|
|
+ acceptSelector.close();
|
|
|
+ }
|
|
|
+ if (Objects.nonNull(serverSocketChannel) && serverSocketChannel.isOpen()) {
|
|
|
+ serverSocketChannel.close();
|
|
|
+ }
|
|
|
+ if (Objects.nonNull(readSelector) && readSelector.isOpen()) {
|
|
|
+ readSelector.close();
|
|
|
+ }
|
|
|
+ if (Objects.nonNull(readHandler)) {
|
|
|
+ readHandler.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void exit(){
|
|
|
+ this.isExit = true;
|
|
|
+ }
|
|
|
+}
|