// // SDLNoticeClient.swift // Tun // // Created by 安礼成 on 2024/5/20. // import Foundation // // SDLanServer.swift // Tun // // Created by 安礼成 on 2024/1/31. // import Foundation import NIOCore import NIOPosix // 处理和sn-server服务器之间的通讯 class SDLNoticeClient: ChannelInboundHandler { public typealias InboundIn = AddressedEnvelope public typealias OutboundOut = AddressedEnvelope private var thread: Thread? var context: ChannelHandlerContext? private let group = MultiThreadedEventLoopGroup(numberOfThreads: 1) private let remoteAddress: SocketAddress init() { self.remoteAddress = try! SocketAddress(ipAddress: "127.0.0.1", port: 50195) } // 启动函数 func start() { self.thread = Thread { let bootstrap = DatagramBootstrap(group: self.group) .channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1) .channelInitializer { channel in // 接收缓冲区 channel.pipeline.addHandler(self) } let channel = try! bootstrap.bind(host: "0.0.0.0", port: 0).wait() SDLLogger.log("[SDLNoticeClient] started and listening on: \(channel.localAddress!)", level: .debug) // This will never unblock as we don't close the channel try! channel.closeFuture.wait() } self.thread?.start() } // -- MARK: ChannelInboundHandler Methods public func channelActive(context: ChannelHandlerContext) { self.context = context } // 接收到的消息, 消息需要根据类型分流 public func channelRead(context: ChannelHandlerContext, data: NIOAny) { context.fireChannelRead(data) } public func errorCaught(context: ChannelHandlerContext, error: Error) { // As we are not really interested getting notified on success or failure we just pass nil as promise to // reduce allocations. context.close(promise: nil) self.context = nil } public func channelInactive(context: ChannelHandlerContext) { self.context = nil context.close(promise: nil) } // 处理写入逻辑 func send(data: Data) { guard let context = self.context else { return } context.eventLoop.execute { let buffer = context.channel.allocator.buffer(bytes: data) let envelope = AddressedEnvelope(remoteAddress: self.remoteAddress, data: buffer) context.writeAndFlush(self.wrapOutboundOut(envelope), promise: nil) } } deinit { self.thread?.cancel() try? self.group.syncShutdownGracefully() } }