From 751b5dda4242024887794b70cd003e9d771ab81f Mon Sep 17 00:00:00 2001 From: tursom Date: Sun, 20 Oct 2019 15:48:16 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=20SocketServer=20=E7=BB=93?= =?UTF-8?q?=E6=9E=84=EF=BC=8C=E6=B7=BB=E5=8A=A0=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- socket/socket-async/README.md | 35 +++ .../kotlin/cn/tursom/socket/AsyncAioClient.kt | 38 +++ .../kotlin/cn/tursom/socket/AsyncClient.kt | 42 --- .../socket/server/AsyncGroupNioServer.kt | 4 +- .../cn/tursom/socket/server/AsyncNioServer.kt | 4 +- .../tursom/socket/server/AsyncSocketServer.kt | 1 - .../socket/server/BuffedAsyncNioServer.kt | 27 ++ .../tursom/socket/server/IAsyncNioServer.kt | 7 + .../kotlin/cn/tursom/socket/BaseSocket.kt | 5 +- .../socket/server/ISimpleSocketServer.kt | 11 + .../server/MultithreadingSocketServer.kt | 28 +- .../socket/server/SingleThreadSocketServer.kt | 18 +- .../cn/tursom/socket/server/SocketServer.kt | 11 - .../socket/server/ThreadPoolSocketServer.kt | 2 +- .../server/SingleThreadSocketServerTest.kt | 21 ++ src/main/kotlin/cn/tursom/core/Tools.kt | 285 +++++++++--------- .../cn/tursom/core/pool/DirectMemoryPool.kt | 76 ++--- .../cn/tursom/core/pool/HeapMemoryPool.kt | 2 +- .../kotlin/cn/tursom/core/pool/MemoryPool.kt | 53 ++-- 19 files changed, 387 insertions(+), 283 deletions(-) create mode 100644 socket/socket-async/README.md create mode 100644 socket/socket-async/src/main/kotlin/cn/tursom/socket/AsyncAioClient.kt delete mode 100644 socket/socket-async/src/main/kotlin/cn/tursom/socket/AsyncClient.kt create mode 100644 socket/socket-async/src/main/kotlin/cn/tursom/socket/server/BuffedAsyncNioServer.kt create mode 100644 socket/socket-async/src/main/kotlin/cn/tursom/socket/server/IAsyncNioServer.kt create mode 100644 socket/src/main/kotlin/cn/tursom/socket/server/ISimpleSocketServer.kt delete mode 100644 socket/src/main/kotlin/cn/tursom/socket/server/SocketServer.kt create mode 100644 socket/src/test/kotlin/cn/tursom/socket/server/SingleThreadSocketServerTest.kt diff --git a/socket/socket-async/README.md b/socket/socket-async/README.md new file mode 100644 index 0000000..0f100b5 --- /dev/null +++ b/socket/socket-async/README.md @@ -0,0 +1,35 @@ +###异步套接字的协程封装 +这个包实现了对异步的套接字的语句同步化封装,适用于 Kotlin 协程执行环境。 +但是因为需要协程作为执行环境,所以无法在 Java 环境下正常创建。 +其核心分别是对 AIO 进行封装的 AsyncAioSocket 和对 NIO 进行封装的 +AsyncNioSocket。AsyncAioSocket 实现简单,但是可塑性较低,缺陷也较难解决; +AsyncNioSocket 虽然实现复杂,但是可塑性很高,优化空间大,缺陷一般也都可以解决。 +--- +AsyncAioSocket 和 AsyncNioSocket 分别通过对应的服务器与客户端创建。 +创建一个异步服务器的形式和同步服务器的形式是完全一样的: + +```kotlin +// 创建一个自带内存池的异步套接字服务器 +val server = BufferedAsyncNioServer(port) { buffer-> + // do any thing + // 这里都是用同步语法写出的异步套接字操作 + read(buffer) + write(buffer) +} +// 异步服务器不需要创建新线程来执行 +server.run() + +// 异步套接字的创建既可以在普通环境下,也可以在协程环境下 +val client = AsyncNioClient.connect("localhost", port) +runBlocking { + val buffer = ByteArrayAdvanceByteBuffer(1024) + // 向套接字内写数据 + buffer.put("Hello!") + client.write(buffer) + // 从套接字内读数据 + buffer.reset() + client.read(buffer) + log(buffer.getString()) + client.close() +} +``` \ No newline at end of file diff --git a/socket/socket-async/src/main/kotlin/cn/tursom/socket/AsyncAioClient.kt b/socket/socket-async/src/main/kotlin/cn/tursom/socket/AsyncAioClient.kt new file mode 100644 index 0000000..660f5fd --- /dev/null +++ b/socket/socket-async/src/main/kotlin/cn/tursom/socket/AsyncAioClient.kt @@ -0,0 +1,38 @@ +package cn.tursom.socket + +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import java.net.InetSocketAddress +import java.net.SocketAddress +import java.nio.channels.AsynchronousSocketChannel +import java.nio.channels.CompletionHandler +import kotlin.coroutines.Continuation +import kotlin.coroutines.resume +import kotlin.coroutines.resumeWithException +import kotlin.coroutines.suspendCoroutine + +object AsyncAioClient { + private val handler = object : CompletionHandler> { + override fun completed(result: Void?, attachment: Continuation) { + GlobalScope.launch { + attachment.resume(result) + } + } + + override fun failed(exc: Throwable, attachment: Continuation) { + GlobalScope.launch { + attachment.resumeWithException(exc) + } + } + } + + suspend fun connect(host: String, port: Int): AsyncAioSocket { + @Suppress("BlockingMethodInNonBlockingContext") + return connect(AsynchronousSocketChannel.open()!!, host, port) + } + + suspend fun connect(socketChannel: AsynchronousSocketChannel, host: String, port: Int): AsyncAioSocket { + suspendCoroutine { cont -> socketChannel.connect(InetSocketAddress(host, port) as SocketAddress, cont, handler) } + return AsyncAioSocket(socketChannel) + } +} \ No newline at end of file diff --git a/socket/socket-async/src/main/kotlin/cn/tursom/socket/AsyncClient.kt b/socket/socket-async/src/main/kotlin/cn/tursom/socket/AsyncClient.kt deleted file mode 100644 index 793a0fa..0000000 --- a/socket/socket-async/src/main/kotlin/cn/tursom/socket/AsyncClient.kt +++ /dev/null @@ -1,42 +0,0 @@ -package cn.tursom.socket - -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch -import java.net.InetSocketAddress -import java.net.SocketAddress -import java.nio.channels.AsynchronousSocketChannel -import java.nio.channels.CompletionHandler -import kotlin.coroutines.Continuation -import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException -import kotlin.coroutines.suspendCoroutine - -object AsyncClient { - private val handler = object : CompletionHandler> { - override fun completed(result: Void?, attachment: Continuation) { - GlobalScope.launch { - attachment.resume(result) - } - } - - override fun failed(exc: Throwable, attachment: Continuation) { - GlobalScope.launch { - attachment.resumeWithException(exc) - } - } - } - - suspend fun connect(host: String, port: Int): AsyncAioSocket { - @Suppress("BlockingMethodInNonBlockingContext") - return connect(AsynchronousSocketChannel.open()!!, host, port) - } - - suspend fun connect(socketChannel: AsynchronousSocketChannel, host: String, port: Int): AsyncAioSocket { - suspendCoroutine { cont -> - socketChannel.connect(InetSocketAddress(host, port) as SocketAddress, cont, - handler - ) - } - return AsyncAioSocket(socketChannel) - } -} \ No newline at end of file diff --git a/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/AsyncGroupNioServer.kt b/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/AsyncGroupNioServer.kt index 65b454c..11bf62e 100644 --- a/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/AsyncGroupNioServer.kt +++ b/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/AsyncGroupNioServer.kt @@ -16,8 +16,8 @@ class AsyncGroupNioServer( override val port: Int, val threads: Int = Runtime.getRuntime().availableProcessors(), backlog: Int = 50, - val handler: suspend AsyncNioSocket.() -> Unit -) : ISocketServer by GroupNioServer( + override val handler: suspend AsyncNioSocket.() -> Unit +) : IAsyncNioServer, ISocketServer by GroupNioServer( port, threads, object : INioProtocol by AsyncNioSocket.nioSocketProtocol { diff --git a/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/AsyncNioServer.kt b/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/AsyncNioServer.kt index cbabe73..7631d57 100644 --- a/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/AsyncNioServer.kt +++ b/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/AsyncNioServer.kt @@ -15,8 +15,8 @@ import java.nio.channels.SelectionKey class AsyncNioServer( override val port: Int, backlog: Int = 50, - val handler: suspend AsyncNioSocket.() -> Unit -) : ISocketServer by NioServer(port, object : INioProtocol by AsyncNioSocket.nioSocketProtocol { + override val handler: suspend AsyncNioSocket.() -> Unit +) : IAsyncNioServer, ISocketServer by NioServer(port, object : INioProtocol by AsyncNioSocket.nioSocketProtocol { override fun handleConnect(key: SelectionKey, nioThread: INioThread) { GlobalScope.launch { val socket = AsyncNioSocket(key, nioThread) diff --git a/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/AsyncSocketServer.kt b/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/AsyncSocketServer.kt index c025ab9..c7b03f1 100644 --- a/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/AsyncSocketServer.kt +++ b/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/AsyncSocketServer.kt @@ -3,7 +3,6 @@ package cn.tursom.socket.server import cn.tursom.socket.AsyncAioSocket import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch -import java.io.Closeable import java.net.InetSocketAddress import java.nio.channels.AsynchronousCloseException import java.nio.channels.AsynchronousServerSocketChannel diff --git a/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/BuffedAsyncNioServer.kt b/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/BuffedAsyncNioServer.kt new file mode 100644 index 0000000..6a2151a --- /dev/null +++ b/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/BuffedAsyncNioServer.kt @@ -0,0 +1,27 @@ +package cn.tursom.socket.server + +import cn.tursom.core.bytebuffer.AdvanceByteBuffer +import cn.tursom.core.bytebuffer.ByteArrayAdvanceByteBuffer +import cn.tursom.core.pool.DirectMemoryPool +import cn.tursom.core.pool.MemoryPool +import cn.tursom.core.pool.usingAdvanceByteBuffer +import cn.tursom.socket.AsyncNioSocket + +class BuffedAsyncNioServer( + port: Int, + backlog: Int = 50, + memoryPool: MemoryPool, + handler: suspend AsyncNioSocket.(buffer: AdvanceByteBuffer) -> Unit +) : IAsyncNioServer by AsyncNioServer(port, backlog, { + memoryPool.usingAdvanceByteBuffer { + handler(it ?: ByteArrayAdvanceByteBuffer(memoryPool.blockSize)) + } +}) { + constructor( + port: Int, + blockSize: Int = 1024, + blockCount: Int = 128, + backlog: Int = 50, + handler: suspend AsyncNioSocket.(buffer: AdvanceByteBuffer) -> Unit + ) : this(port, backlog, DirectMemoryPool(blockSize, blockCount), handler) +} \ No newline at end of file diff --git a/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/IAsyncNioServer.kt b/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/IAsyncNioServer.kt new file mode 100644 index 0000000..37a38cf --- /dev/null +++ b/socket/socket-async/src/main/kotlin/cn/tursom/socket/server/IAsyncNioServer.kt @@ -0,0 +1,7 @@ +package cn.tursom.socket.server + +import cn.tursom.socket.AsyncNioSocket + +interface IAsyncNioServer : ISocketServer { + val handler: suspend AsyncNioSocket.() -> Unit +} \ No newline at end of file diff --git a/socket/src/main/kotlin/cn/tursom/socket/BaseSocket.kt b/socket/src/main/kotlin/cn/tursom/socket/BaseSocket.kt index 94b1cb7..5d6deeb 100644 --- a/socket/src/main/kotlin/cn/tursom/socket/BaseSocket.kt +++ b/socket/src/main/kotlin/cn/tursom/socket/BaseSocket.kt @@ -1,9 +1,8 @@ package cn.tursom.socket -import cn.tursom.core.* -import java.io.* +import cn.tursom.core.put +import java.io.Closeable import java.net.Socket -import java.net.SocketTimeoutException /** * 对基础的Socket做了些许封装 diff --git a/socket/src/main/kotlin/cn/tursom/socket/server/ISimpleSocketServer.kt b/socket/src/main/kotlin/cn/tursom/socket/server/ISimpleSocketServer.kt new file mode 100644 index 0000000..a415f66 --- /dev/null +++ b/socket/src/main/kotlin/cn/tursom/socket/server/ISimpleSocketServer.kt @@ -0,0 +1,11 @@ +package cn.tursom.socket.server + +import cn.tursom.socket.BaseSocket + +interface ISimpleSocketServer : ISocketServer { + val handler: BaseSocket.() -> Unit + + interface Handler { + fun handle(socket: BaseSocket) + } +} \ No newline at end of file diff --git a/socket/src/main/kotlin/cn/tursom/socket/server/MultithreadingSocketServer.kt b/socket/src/main/kotlin/cn/tursom/socket/server/MultithreadingSocketServer.kt index e6b14d8..933010e 100644 --- a/socket/src/main/kotlin/cn/tursom/socket/server/MultithreadingSocketServer.kt +++ b/socket/src/main/kotlin/cn/tursom/socket/server/MultithreadingSocketServer.kt @@ -4,29 +4,37 @@ import cn.tursom.core.cpuNumber import cn.tursom.socket.BaseSocket import java.net.ServerSocket +/** + * 这是一个自动启用多个线程来处理请求的套接字服务器 + */ class MultithreadingSocketServer( private val serverSocket: ServerSocket, private val threadNumber: Int = cpuNumber, - val exception: Exception.() -> Unit = { - printStackTrace() - }, override val handler: BaseSocket.() -> Unit -) : SocketServer { +) : ISimpleSocketServer { override val port = serverSocket.localPort constructor( port: Int, threadNumber: Int = cpuNumber, - exception: Exception.() -> Unit = { - printStackTrace() - }, handler: BaseSocket.() -> Unit - ) : this(ServerSocket(port), threadNumber, exception, handler) + ) : this(ServerSocket(port), threadNumber, handler) constructor( port: Int, handler: BaseSocket.() -> Unit - ) : this(port, cpuNumber, { printStackTrace() }, handler) + ) : this(port, cpuNumber, handler) + + constructor( + port: Int, + threadNumber: Int = cpuNumber, + handler: ISimpleSocketServer.Handler + ) : this(ServerSocket(port), threadNumber, handler::handle) + + constructor( + port: Int, + handler: ISimpleSocketServer.Handler + ) : this(port, cpuNumber, handler::handle) private val threadList = ArrayList() @@ -38,7 +46,7 @@ class MultithreadingSocketServer( try { BaseSocket(it).handler() } catch (e: Exception) { - e.exception() + e.printStackTrace() } } } diff --git a/socket/src/main/kotlin/cn/tursom/socket/server/SingleThreadSocketServer.kt b/socket/src/main/kotlin/cn/tursom/socket/server/SingleThreadSocketServer.kt index 800e18c..402c089 100644 --- a/socket/src/main/kotlin/cn/tursom/socket/server/SingleThreadSocketServer.kt +++ b/socket/src/main/kotlin/cn/tursom/socket/server/SingleThreadSocketServer.kt @@ -4,23 +4,25 @@ import cn.tursom.socket.BaseSocket import java.net.ServerSocket import java.net.SocketException +/** + * 单线程套接字服务器 + * 可以用多个线程同时运行该服务器,可以正常工作 + */ class SingleThreadSocketServer( private val serverSocket: ServerSocket, - val exception: Exception.() -> Unit = { printStackTrace() }, override val handler: BaseSocket.() -> Unit -) : SocketServer { +) : ISimpleSocketServer { override val port = serverSocket.localPort constructor( port: Int, - exception: Exception.() -> Unit = { printStackTrace() }, handler: BaseSocket.() -> Unit - ) : this(ServerSocket(port), exception, handler) + ) : this(ServerSocket(port), handler) constructor( port: Int, - handler: BaseSocket.() -> Unit - ) : this(port, { printStackTrace() }, handler) + handler: ISimpleSocketServer.Handler + ) : this(ServerSocket(port), handler::handle) override fun run() { while (!serverSocket.isClosed) { @@ -29,14 +31,14 @@ class SingleThreadSocketServer( try { BaseSocket(it).handler() } catch (e: Exception) { - e.exception() + e.printStackTrace() } } } catch (e: SocketException) { if (e.message == "Socket closed" || e.message == "cn.tursom.socket closed") { break } else { - e.exception() + e.printStackTrace() } } } diff --git a/socket/src/main/kotlin/cn/tursom/socket/server/SocketServer.kt b/socket/src/main/kotlin/cn/tursom/socket/server/SocketServer.kt deleted file mode 100644 index f4ecfe7..0000000 --- a/socket/src/main/kotlin/cn/tursom/socket/server/SocketServer.kt +++ /dev/null @@ -1,11 +0,0 @@ -package cn.tursom.socket.server - -import cn.tursom.socket.BaseSocket - -interface SocketServer : ISocketServer { - val handler: BaseSocket.() -> Unit - - companion object { - val cpuNumber = Runtime.getRuntime().availableProcessors() //CPU处理器的个数 - } -} \ No newline at end of file diff --git a/socket/src/main/kotlin/cn/tursom/socket/server/ThreadPoolSocketServer.kt b/socket/src/main/kotlin/cn/tursom/socket/server/ThreadPoolSocketServer.kt index 64280a6..352c957 100644 --- a/socket/src/main/kotlin/cn/tursom/socket/server/ThreadPoolSocketServer.kt +++ b/socket/src/main/kotlin/cn/tursom/socket/server/ThreadPoolSocketServer.kt @@ -47,7 +47,7 @@ class ThreadPoolSocketServer keepAliveTime: Long = 60_000L, timeUnit: TimeUnit = TimeUnit.MILLISECONDS, override val handler: BaseSocket.() -> Unit -) : SocketServer { +) : ISimpleSocketServer { constructor( port: Int, diff --git a/socket/src/test/kotlin/cn/tursom/socket/server/SingleThreadSocketServerTest.kt b/socket/src/test/kotlin/cn/tursom/socket/server/SingleThreadSocketServerTest.kt new file mode 100644 index 0000000..12c26b7 --- /dev/null +++ b/socket/src/test/kotlin/cn/tursom/socket/server/SingleThreadSocketServerTest.kt @@ -0,0 +1,21 @@ +package cn.tursom.socket.server + +import cn.tursom.socket.BaseSocket +import org.junit.Test + +class SingleThreadSocketServerTest { + @Test + fun testCreateServer() { + val port = 12345 + + // Kotlin 写法 + SingleThreadSocketServer(port) { + }.close() + + // Java 写法 + SingleThreadSocketServer(port, object : ISimpleSocketServer.Handler { + override fun handle(socket: BaseSocket) { + } + }).close() + } +} \ No newline at end of file diff --git a/src/main/kotlin/cn/tursom/core/Tools.kt b/src/main/kotlin/cn/tursom/core/Tools.kt index 83f35a2..e74fb91 100644 --- a/src/main/kotlin/cn/tursom/core/Tools.kt +++ b/src/main/kotlin/cn/tursom/core/Tools.kt @@ -1,26 +1,35 @@ +@file:Suppress("unused") + package cn.tursom.core import sun.misc.Unsafe import java.lang.reflect.ParameterizedType +import java.lang.reflect.Type import java.net.URLDecoder import java.net.URLEncoder import java.security.MessageDigest import java.security.NoSuchAlgorithmException import java.util.* import java.util.jar.JarFile +import kotlin.collections.ArrayList + +inline fun Array.excludeNull(): List { + val list = ArrayList() + forEach { if (it != null) list.add(it) } + return list +} fun printNonDaemonThread() { - val currentGroup = Thread.currentThread().threadGroup - val noThreads = currentGroup.activeCount() - val lstThreads = arrayOfNulls(noThreads) - currentGroup.enumerate(lstThreads) - for (i in 0 until noThreads) { - val t = lstThreads[i] - if (t?.isDaemon != true) { - println("${System.currentTimeMillis()}: ${t?.name}") - } - } - println() + val currentGroup = Thread.currentThread().threadGroup + val noThreads = currentGroup.activeCount() + val lstThreads = arrayOfNulls(noThreads) + currentGroup.enumerate(lstThreads) + lstThreads.excludeNull().forEach { t -> + if (!t.isDaemon) { + println("${System.currentTimeMillis()}: ${t.name}") + } + } + println() } fun log(log: String) = println("${System.currentTimeMillis()}: $log") @@ -31,184 +40,182 @@ val String.urlDecode: String get() = URLDecoder.decode(this, "utf-8") val String.urlEncode: String get() = URLEncoder.encode(this, "utf-8") inline fun usingTime(action: () -> T): Long { - val t1 = System.currentTimeMillis() - action() - val t2 = System.currentTimeMillis() - return t2 - t1 + val t1 = System.currentTimeMillis() + action() + val t2 = System.currentTimeMillis() + return t2 - t1 } -inline fun Collection.doEach(block: (T) -> Any): String { - val iterator = iterator() - if (!iterator.hasNext()) return "[]" - val sb = StringBuilder("[${block(iterator.next())}") - iterator.forEach { - sb.append(", ") - sb.append(block(it)) - } - sb.append("]") - return sb.toString() +inline fun Collection.toString(action: (T) -> Any): String { + val iterator = iterator() + if (!iterator.hasNext()) return "[]" + val sb = StringBuilder("[${action(iterator.next())}") + iterator.forEach { + sb.append(", ") + sb.append(action(it)) + } + sb.append("]") + return sb.toString() } -//利用Unsafe绕过构造函数获取变量 val unsafe by lazy { - val field = Unsafe::class.java.getDeclaredField("theUnsafe") - //允许通过反射设置属性的值 - field.isAccessible = true - field.get(null) as Unsafe + val field = Unsafe::class.java.getDeclaredField("theUnsafe") + field.isAccessible = true + field.get(null) as Unsafe } @Suppress("UNCHECKED_CAST") fun Class.unsafeInstance() = unsafe.allocateInstance(this) as T -val Class<*>.actualTypeArguments +val Class<*>.actualTypeArguments: Array get() = (genericSuperclass as ParameterizedType).actualTypeArguments fun Class<*>.isInheritanceFrom(parent: Class<*>) = parent.isAssignableFrom(this) fun getClassName(jarPath: String): List { - val myClassName = ArrayList() - for (entry in JarFile(jarPath).entries()) { - val entryName = entry.name - if (entryName.endsWith(".class")) { - myClassName.add(entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."))) - } - } - return myClassName + val myClassName = ArrayList() + for (entry in JarFile(jarPath).entries()) { + val entryName = entry.name + if (entryName.endsWith(".class")) { + myClassName.add(entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."))) + } + } + return myClassName } fun List.binarySearch(comparison: (T) -> Int): T? { - val index = binarySearch(0, size, comparison) - return if (index < 0) null - else get(index) + val index = binarySearch(0, size, comparison) + return if (index < 0) null + else get(index) } val cpuNumber = Runtime.getRuntime().availableProcessors() fun String.simplifyPath(): String { - if (isEmpty()) { - return "/" - } - val strs = split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() - val list = LinkedList() - for (str in strs) { - if (str.isEmpty() || "." == str) { - continue - } - if (".." == str) { - list.pollLast() - continue - } - list.addLast(str) - } - var result = "" - while (list.size > 0) { - result += "/" + list.pollFirst()!! - } - return if (result.isNotEmpty()) result else "/" + if (isEmpty()) { + return "." + } + val pathList = split(java.io.File.separator).dropLastWhile { it.isEmpty() } + val list = LinkedList() + for (path in pathList) { + if (path.isEmpty() || "." == path) { + continue + } + if (".." == path) { + list.pollLast() + continue + } + list.addLast(path) + } + var result = "" + while (list.size > 0) { + result += java.io.File.separator + list.pollFirst()!! + } + return if (result.isNotEmpty()) result else "." } fun ByteArray.md5(): ByteArray? { - return try { - //获取md5加密对象 - val instance = MessageDigest.getInstance("MD5") - //加密,返回字节数组 - instance.digest(this) - } catch (e: NoSuchAlgorithmException) { - e.printStackTrace() - null - } + return try { + //获取md5加密对象 + val instance = MessageDigest.getInstance("MD5") + //加密,返回字节数组 + instance.digest(this) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + null + } } fun String.md5(): String? { - return toByteArray().md5()?.toHexString() + return toByteArray().md5()?.toHexString() } fun ByteArray.sha256(): ByteArray? { - return try { - //获取md5加密对象 - val instance = MessageDigest.getInstance("SHA-256") - //加密,返回字节数组 - instance.digest(this) - } catch (e: NoSuchAlgorithmException) { - e.printStackTrace() - null - } + return try { + //获取md5加密对象 + val instance = MessageDigest.getInstance("SHA-256") + //加密,返回字节数组 + instance.digest(this) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + null + } } fun String.sha256(): String? { - return toByteArray().sha256()?.toHexString() + return toByteArray().sha256()?.toHexString() } fun ByteArray.sha(): ByteArray? { - return try { - //获取md5加密对象 - val instance = MessageDigest.getInstance("SHA") - //对字符串加密,返回字节数组 - instance.digest(this) - } catch (e: NoSuchAlgorithmException) { - e.printStackTrace() - null - } + return try { + //获取md5加密对象 + val instance = MessageDigest.getInstance("SHA") + //对字符串加密,返回字节数组 + instance.digest(this) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + null + } } fun String.sha(): String? = toByteArray().sha()?.toHexString() fun ByteArray.sha1(): ByteArray? { - return try { - //获取md5加密对象 - val instance = MessageDigest.getInstance("SHA-1") - //对字符串加密,返回字节数组 - instance.digest(this) - } catch (e: NoSuchAlgorithmException) { - e.printStackTrace() - null - } + return try { + //获取md5加密对象 + val instance = MessageDigest.getInstance("SHA-1") + //对字符串加密,返回字节数组 + instance.digest(this) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + null + } } fun String.sha1(): String? = toByteArray().sha1()?.toHexString() fun ByteArray.sha384(): ByteArray? { - return try { - //获取md5加密对象 - val instance = MessageDigest.getInstance("SHA-384") - //对字符串加密,返回字节数组 - instance.digest(this) - } catch (e: NoSuchAlgorithmException) { - e.printStackTrace() - null - } + return try { + //获取md5加密对象 + val instance = MessageDigest.getInstance("SHA-384") + //对字符串加密,返回字节数组 + instance.digest(this) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + null + } } fun String.sha384(): String? = toByteArray().sha384()?.toHexString() fun ByteArray.sha512(): ByteArray? { - return try { - //获取md5加密对象 - val instance = MessageDigest.getInstance("SHA-512") - //对字符串加密,返回字节数组 - instance.digest(this) - } catch (e: NoSuchAlgorithmException) { - e.printStackTrace() - null - } + return try { + //获取md5加密对象 + val instance = MessageDigest.getInstance("SHA-512") + //对字符串加密,返回字节数组 + instance.digest(this) + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + null + } } fun String.sha512(): String? = toByteArray().sha512()?.toHexString() fun ByteArray.toHexString(): String? { - val sb = StringBuilder() - forEach { - //获取低八位有效值+ - val i: Int = it.toInt() and 0xff - //将整数转化为16进制 - var hexString = Integer.toHexString(i) - if (hexString.length < 2) { - //如果是一位的话,补0 - hexString = "0$hexString" - } - sb.append(hexString) - } - return sb.toString() + val sb = StringBuilder() + forEach { + //获取低八位有效值+ + val i: Int = it.toInt() and 0xff + //将整数转化为16进制 + var hexString = Integer.toHexString(i) + if (hexString.length < 2) { + //如果是一位的话,补0 + hexString = "0$hexString" + } + sb.append(hexString) + } + return sb.toString() } fun ByteArray.toUTF8String() = String(this, Charsets.UTF_8) @@ -216,7 +223,7 @@ fun ByteArray.toUTF8String() = String(this, Charsets.UTF_8) fun String.base64() = this.toByteArray().base64().toUTF8String() fun ByteArray.base64(): ByteArray { - return Base64.getEncoder().encode(this) + return Base64.getEncoder().encode(this) } fun String.base64decode() = Base64.getDecoder().decode(this).toUTF8String() @@ -226,18 +233,18 @@ fun ByteArray.base64decode(): ByteArray = Base64.getDecoder().decode(this) fun String.digest(type: String) = toByteArray().digest(type)?.toHexString() fun ByteArray.digest(type: String) = try { - //获取加密对象 - val instance = MessageDigest.getInstance(type) - //加密,返回字节数组 - instance.digest(this) + //获取加密对象 + val instance = MessageDigest.getInstance(type) + //加密,返回字节数组 + instance.digest(this) } catch (e: NoSuchAlgorithmException) { - e.printStackTrace() - null + e.printStackTrace() + null } fun randomInt(min: Int, max: Int) = Random().nextInt(max) % (max - min + 1) + min fun getTAG(cls: Class<*>): String { - return cls.name.split(".").last().dropLast(10) + return cls.name.split(".").last().dropLast(10) } diff --git a/src/main/kotlin/cn/tursom/core/pool/DirectMemoryPool.kt b/src/main/kotlin/cn/tursom/core/pool/DirectMemoryPool.kt index 6a0628f..3b75cb4 100644 --- a/src/main/kotlin/cn/tursom/core/pool/DirectMemoryPool.kt +++ b/src/main/kotlin/cn/tursom/core/pool/DirectMemoryPool.kt @@ -5,46 +5,46 @@ import cn.tursom.core.bytebuffer.NioAdvanceByteBuffer import cn.tursom.core.datastruct.ArrayBitSet import java.nio.ByteBuffer -class DirectMemoryPool(val blockSize: Int = 1024, val blockCount: Int = 16) : MemoryPool { - private val memoryPool = ByteBuffer.allocateDirect(blockSize * blockCount) - private val bitMap = ArrayBitSet(blockCount.toLong()) +class DirectMemoryPool(override val blockSize: Int = 1024, override val blockCount: Int = 16) : MemoryPool { + private val memoryPool = ByteBuffer.allocateDirect(blockSize * blockCount) + private val bitMap = ArrayBitSet(blockCount.toLong()) - /** - * @return token - */ - override fun allocate(): Int = synchronized(this) { - val index = bitMap.firstDown() - if (index in 0 until blockCount) { - bitMap.up(index) - index.toInt() - } else { - -1 - } - } + /** + * @return token + */ + override fun allocate(): Int = synchronized(this) { + val index = bitMap.firstDown() + if (index in 0 until blockCount) { + bitMap.up(index) + index.toInt() + } else { + -1 + } + } - override fun free(token: Int) { - if (token in 0 until blockCount) synchronized(this) { - bitMap.down(token.toLong()) - } - } + override fun free(token: Int) { + if (token in 0 until blockCount) synchronized(this) { + bitMap.down(token.toLong()) + } + } - override fun getMemory(token: Int): ByteBuffer? = if (token in 0 until blockCount) { - synchronized(this) { - memoryPool.limit((token + 1) * blockSize) - memoryPool.position(token * blockSize) - return memoryPool.slice() - } - } else { - null - } + override fun getMemory(token: Int): ByteBuffer? = if (token in 0 until blockCount) { + synchronized(this) { + memoryPool.limit((token + 1) * blockSize) + memoryPool.position(token * blockSize) + return memoryPool.slice() + } + } else { + null + } - override fun getAdvanceByteBuffer(token: Int): AdvanceByteBuffer? = if (token in 0 until blockCount) { - synchronized(this) { - memoryPool.limit((token + 1) * blockSize) - memoryPool.position(token * blockSize) - return NioAdvanceByteBuffer(memoryPool.slice()) - } - } else { - null - } + override fun getAdvanceByteBuffer(token: Int): AdvanceByteBuffer? = if (token in 0 until blockCount) { + synchronized(this) { + memoryPool.limit((token + 1) * blockSize) + memoryPool.position(token * blockSize) + return NioAdvanceByteBuffer(memoryPool.slice()) + } + } else { + null + } } \ No newline at end of file diff --git a/src/main/kotlin/cn/tursom/core/pool/HeapMemoryPool.kt b/src/main/kotlin/cn/tursom/core/pool/HeapMemoryPool.kt index 1f32c3b..78a9018 100644 --- a/src/main/kotlin/cn/tursom/core/pool/HeapMemoryPool.kt +++ b/src/main/kotlin/cn/tursom/core/pool/HeapMemoryPool.kt @@ -6,7 +6,7 @@ import cn.tursom.core.datastruct.ArrayBitSet import java.nio.ByteBuffer @Suppress("MemberVisibilityCanBePrivate") -class HeapMemoryPool(val blockSize: Int = 1024, val blockCount: Int = 16) : MemoryPool { +class HeapMemoryPool(override val blockSize: Int = 1024, override val blockCount: Int = 16) : MemoryPool { private val memoryPool = ByteBuffer.allocate(blockSize * blockCount) private val bitMap = ArrayBitSet(blockCount.toLong()) diff --git a/src/main/kotlin/cn/tursom/core/pool/MemoryPool.kt b/src/main/kotlin/cn/tursom/core/pool/MemoryPool.kt index 969c1d7..9ab0162 100644 --- a/src/main/kotlin/cn/tursom/core/pool/MemoryPool.kt +++ b/src/main/kotlin/cn/tursom/core/pool/MemoryPool.kt @@ -5,34 +5,37 @@ import cn.tursom.core.bytebuffer.NioAdvanceByteBuffer import java.nio.ByteBuffer interface MemoryPool { - fun allocate(): Int - fun free(token: Int) - fun getMemory(token: Int): ByteBuffer? - fun getAdvanceByteBuffer(token: Int): AdvanceByteBuffer? { - val buffer = getMemory(token) - return if (buffer != null) { - NioAdvanceByteBuffer(buffer) - } else { - null - } - } + val blockSize: Int + val blockCount: Int + + fun allocate(): Int + fun free(token: Int) + fun getMemory(token: Int): ByteBuffer? + fun getAdvanceByteBuffer(token: Int): AdvanceByteBuffer? { + val buffer = getMemory(token) + return if (buffer != null) { + NioAdvanceByteBuffer(buffer) + } else { + null + } + } } -inline fun MemoryPool.usingMemory(action: (ByteBuffer?) -> Unit) { - val token = allocate() - try { - action(getMemory(token)) - } finally { - free(token) - } +inline fun MemoryPool.usingMemory(action: (ByteBuffer?) -> T): T { + val token = allocate() + return try { + action(getMemory(token)) + } finally { + free(token) + } } -inline fun MemoryPool.usingAdvanceByteBuffer(action: (AdvanceByteBuffer?) -> Unit) { - val token = allocate() - try { - action(getAdvanceByteBuffer(token)) - } finally { - free(token) - } +inline fun MemoryPool.usingAdvanceByteBuffer(action: (AdvanceByteBuffer?) -> T): T { + val token = allocate() + return try { + action(getAdvanceByteBuffer(token)) + } finally { + free(token) + } } \ No newline at end of file