diff --git a/build.gradle.kts b/build.gradle.kts index 5c3e672..af47839 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2025 mingliqiye + * Copyright 2026 mingliqiye * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils * CurrentFile build.gradle.kts - * LastUpdate 2025-09-21 15:36:59 + * LastUpdate 2026-01-06 14:05:20 * UpdateUser MingLiPro */ @@ -69,14 +69,14 @@ dependencies { implementation("org.slf4j:slf4j-api:2.0.17") implementation("com.mingliqiye.utils.jna:WinKernel32Api:1.0.1") - // https://github.com/jeremyh/jBCrypt - implementation("org.mindrot:jbcrypt:0.4") + compileOnly("org.mindrot:jbcrypt:0.4") compileOnly("org.springframework.boot:spring-boot-starter:2.7.14") compileOnly("com.fasterxml.jackson.core:jackson-databind:2.19.2") compileOnly("com.google.code.gson:gson:2.13.1") compileOnly("org.mybatis:mybatis:3.5.19") compileOnly("com.alibaba.fastjson2:fastjson2:2.0.58") + compileOnly("io.netty:netty-all:4.2.9.Final") compileOnly("com.baomidou:mybatis-plus-core:3.0.1") compileOnly("net.java.dev.jna:jna:5.17.0") diff --git a/gradle.properties b/gradle.properties index 7c8d122..dccb840 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # -# Copyright 2025 mingliqiye +# Copyright 2026 mingliqiye # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,13 +16,13 @@ # ProjectName mingli-utils # ModuleName mingli-utils # CurrentFile gradle.properties -# LastUpdate 2025-09-21 21:55:23 +# LastUpdate 2026-01-06 14:35:41 # UpdateUser MingLiPro # JDKVERSIONS=1.8 GROUPSID=com.mingliqiye.utils ARTIFACTID=mingli-utils -VERSIONS=4.2.4 +VERSIONS=4.2.6 signing.keyId=B22AA93B signing.password= signing.secretKeyRingFile=secret.gpg diff --git a/src/main/kotlin/com/mingliqiye/utils/Main.kt b/src/main/kotlin/com/mingliqiye/utils/Main.kt new file mode 100644 index 0000000..93a4798 --- /dev/null +++ b/src/main/kotlin/com/mingliqiye/utils/Main.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2026 mingliqiye + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ProjectName mingli-utils + * ModuleName mingli-utils.main + * CurrentFile Main.kt + * LastUpdate 2026-01-06 14:04:14 + * UpdateUser MingLiPro + */ + +package com.mingliqiye.utils + +import com.mingliqiye.utils.network.NetworkEndpoint +import com.mingliqiye.utils.uuid.UUID +import java.nio.ByteBuffer + +fun main() { + val byteBuffer = ByteBuffer.allocate(320) + NetworkEndpoint + .of("0:65532") + .writeIpv4toByteBuffer(byteBuffer) + + UUID.getMaxUUID().writeToByteBuffer(byteBuffer) + + byteBuffer.flip() + + println(NetworkEndpoint.ofIpv4(byteBuffer)) + println(UUID.of(byteBuffer)) + +} diff --git a/src/main/kotlin/com/mingliqiye/utils/main/Main.kt b/src/main/kotlin/com/mingliqiye/utils/main/Main.kt index ba602e9..6ff2225 100644 --- a/src/main/kotlin/com/mingliqiye/utils/main/Main.kt +++ b/src/main/kotlin/com/mingliqiye/utils/main/Main.kt @@ -1,5 +1,5 @@ /* - * Copyright 2025 mingliqiye + * Copyright 2026 mingliqiye * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile Main.kt - * LastUpdate 2025-09-20 13:22:11 + * LastUpdate 2026-01-06 14:36:10 * UpdateUser MingLiPro */ @file:JvmName("Main") @@ -24,12 +24,7 @@ package com.mingliqiye.utils.main import com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration -import com.mingliqiye.utils.stream.SuperStream fun main() { AutoConfiguration.printBanner() - val data = SuperStream.of(Array(0) { 1 }) - - - println(data) } diff --git a/src/main/kotlin/com/mingliqiye/utils/netty/NettyUtils.kt b/src/main/kotlin/com/mingliqiye/utils/netty/NettyUtils.kt new file mode 100644 index 0000000..4a1d62d --- /dev/null +++ b/src/main/kotlin/com/mingliqiye/utils/netty/NettyUtils.kt @@ -0,0 +1,90 @@ +/* + * Copyright 2026 mingliqiye + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ProjectName mingli-utils + * ModuleName mingli-utils.main + * CurrentFile NettyUtils.kt + * LastUpdate 2026-01-06 14:33:44 + * UpdateUser MingLiPro + */ + +@file:JvmName("NettyUtils") + +package com.mingliqiye.utils.netty + +import io.netty.buffer.ByteBuf +import io.netty.buffer.Unpooled +import java.nio.ByteBuffer + +/** + * 将ByteBuffer转换为Netty的ByteBuf对象 + * + * 该函数使用Netty库的Unpooled工具类将标准的java.nio.ByteBuffer包装成Netty的ByteBuf + * 以便在Netty框架中使用 + * + * @receiver ByteBuffer 需要转换的原始ByteBuffer对象 + * @return ByteBuf 转换后的Netty ByteBuf对象,该对象包装了原始的ByteBuffer + */ +fun ByteBuffer.toByteBuf(): ByteBuf { + return Unpooled.wrappedBuffer(this) +} + +/** + * 将Netty的ByteBuf对象转换为ByteBuffer + * + * 该函数通过ByteBuf的nioBuffer()方法将Netty的ByteBuf转换为标准的java.nio.ByteBuffer + * + * @receiver ByteBuf 需要转换的原始ByteBuf对象 + * @return ByteBuffer 转换后的java.nio.ByteBuffer对象 + */ +fun ByteBuf.toByteBuffer(): ByteBuffer { + return this.nioBuffer() +} + +/** + * 将Netty的ByteBuf对象转换为字节数组 + * + * 该函数将ByteBuf中的可读字节读取到一个新的字节数组中 + * + * @receiver ByteBuf 需要转换的原始ByteBuf对象 + * @return ByteArray 转换后的字节数组,包含ByteBuf中所有可读的字节数据 + */ +fun ByteBuf.toByteArray(): ByteArray { + val array = ByteArray(this.readableBytes()) + this.readBytes(array) + return array +} + +/** + * 将字节数组转换为Netty的ByteBuf对象 + * + * 该函数使用Netty库的Unpooled工具类将字节数组包装成Netty的ByteBuf + * 以便在Netty框架中使用 + * + * @receiver ByteArray 需要转换的原始字节数组 + * @return ByteBuf 转换后的Netty ByteBuf对象,该对象包装了原始的字节数组 + */ +fun ByteArray.toByteBuf(): ByteBuf { + return Unpooled.wrappedBuffer(this) +} + +/** + * 将字节数组转换为ByteBuffer对象 + * + * @return 转换后的ByteBuffer对象,该ByteBuffer包装了原始字节数组 + */ +fun ByteArray.toByteBuffer(): ByteBuffer { + return ByteBuffer.wrap(this) +} diff --git a/src/main/kotlin/com/mingliqiye/utils/network/AddressPort.kt b/src/main/kotlin/com/mingliqiye/utils/network/AddressPort.kt index fa4a5c0..88b210f 100644 --- a/src/main/kotlin/com/mingliqiye/utils/network/AddressPort.kt +++ b/src/main/kotlin/com/mingliqiye/utils/network/AddressPort.kt @@ -1,5 +1,5 @@ /* - * Copyright 2025 mingliqiye + * Copyright 2026 mingliqiye * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,16 +16,18 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile AddressPort.kt - * LastUpdate 2025-09-15 22:01:27 + * LastUpdate 2026-01-06 14:03:47 * UpdateUser MingLiPro */ package com.mingliqiye.utils.network +import com.mingliqiye.utils.string.join import java.io.Serializable import java.net.InetAddress import java.net.InetSocketAddress import java.net.UnknownHostException +import java.nio.ByteBuffer import java.util.regex.Pattern /** @@ -80,6 +82,20 @@ class NetworkAddress private constructor(domip: String) : Serializable { return NetworkAddress(domip) } + @JvmStatic + fun ofIpv4(byteBuffer: ByteBuffer): NetworkAddress { + val byteArray = ByteArray(4) + byteBuffer.get(byteArray) + return ofIpv4(byteArray) + } + + @JvmStatic + fun ofIpv4(byteArray: ByteArray): NetworkAddress { + return of(".".join(byteArray.map { + (it.toInt() and 0xFF).toString() + })) + } + /** * 静态工厂方法,通过 InetAddress 创建 NetworkAddress 实例。 * @@ -182,6 +198,31 @@ class NetworkAddress private constructor(domip: String) : Serializable { } } + /** + * 将IPv4地址转换为字节数组 + * + * @return 返回表示IPv4地址的4字节数组 + * @throws NetworkException 当当前地址不是IPv4地址时抛出异常 + */ + fun toIpv4ByteArray(): ByteArray { + // 验证地址类型是否为IPv4 + if (iPv != IPV4) { + throw NetworkException("该地址 不是IPv4地址") + } + // 将IP地址字符串按点分割,转换为整数并进行位运算处理,最后转为字节数组 + return ip!!.split(".").map { it.toInt() and 0xFF }.map { it.toByte() }.toByteArray() + } + + /** + * 将IPv4地址写入到指定的ByteBuffer中 + * + * @param byteBuffer 要写入的ByteBuffer对象,IPv4地址将以字节数组形式写入到该缓冲区 + * @return 返回写入了IPv4地址的ByteBuffer对象,便于链式调用 + */ + fun writeIpv4ToByteBuffer(byteBuffer: ByteBuffer): ByteBuffer { + return byteBuffer.put(toIpv4ByteArray()) + } + /** * 将当前 NetworkAddress 转换为 InetAddress 对象。 * @@ -215,7 +256,54 @@ class NetworkPort : Serializable { this.port = port } + fun toByteArray(): ByteArray { + val byteArray = ByteArray(2) + byteArray[0] = (port shr 8 and 0xFF).toByte() + byteArray[1] = (port and 0xFF).toByte() + return byteArray + } + + fun writeToByteBuffer(byteBuffer: ByteBuffer): ByteBuffer { + return byteBuffer.put(toByteArray()) + } + companion object { + + /** + * 创建NetworkPort实例 + * @param port 端口号 + * @return NetworkPort实例 + */ + @JvmStatic + fun of(port: Int): NetworkPort { + return NetworkPort(port) + } + + /** + * 从字节数组创建NetworkPort实例 + * @param byteArray 包含端口信息的字节数组(长度至少为2) + * @return NetworkPort实例 + */ + @JvmStatic + fun of(byteArray: ByteArray): NetworkPort { + // 将字节数组的前两个字节转换为端口号 + val port = ((byteArray[0].toInt() and 0xFF) shl 8) or (byteArray[1].toInt() and 0xFF) + return of(port) + } + + /** + * 从ByteBuffer创建NetworkPort实例 + * @param byteBuffer 包含端口信息的ByteBuffer + * @return NetworkPort实例 + */ + @JvmStatic + fun of(byteBuffer: ByteBuffer): NetworkPort { + val byteArray = ByteArray(2) + byteBuffer.get(byteArray) + return of(byteArray) + } + + @JvmStatic fun testPort(port: Int) { // 验证端口号范围是否在0-65535之间 if (port !in 0..65535) { @@ -282,6 +370,42 @@ class NetworkEndpoint private constructor( return NetworkEndpoint(networkAddress, networkPort) } + /** + * 从字节数组创建IPv4网络端点 + * + * @param byteArray 包含IPv4地址和端口信息的字节数组,前4个字节表示IP地址,后2个字节表示端口号 + * @return NetworkEndpoint对象,封装了IPv4地址和端口信息 + */ + @JvmStatic + fun ofIpv4(byteArray: ByteArray): NetworkEndpoint { + // 提取前4个字节作为IP地址 + val address = ByteArray(4) { + byteArray[it] + } + // 提取后2个字节作为端口号 + val portInt = ByteArray(2) { + byteArray[it + 4] + } + return NetworkEndpoint(NetworkAddress.ofIpv4(address), NetworkPort.of(portInt)) + } + + /** + * 从字节缓冲区创建IPv4网络端点实例 + * + * 该方法从给定的ByteBuffer中读取数据,构建一个包含IPv4地址和端口的网络端点对象。 + * 该方法按照协议顺序从缓冲区中读取IPv4地址数据和端口数据。 + * + * @param byteBuffer 包含IPv4地址和端口数据的字节缓冲区,缓冲区中的数据应按照先地址后端口的顺序排列 + * @return 返回一个NetworkEndpoint实例,包含从缓冲区解析出的IPv4地址和端口信息 + */ + @JvmStatic + fun ofIpv4(byteBuffer: ByteBuffer): NetworkEndpoint { + return NetworkEndpoint( + NetworkAddress.ofIpv4(byteBuffer), + NetworkPort.of(byteBuffer) + ) + } + /** * 根据"host:port"格式的字符串创建NetworkEndpoint实例。 * 例如:"127.0.0.1:8080" @@ -327,7 +451,7 @@ class NetworkEndpoint private constructor( * @return 包含详细信息的字符串 */ override fun toString(): String { - return "NetworkEndpoint(IP=${networkAddress.ip},Port=${networkPort.port},Endpoint=${toHostPortString()})" + return "NetworkEndpoint(IP=${networkAddress.ip},Port=${networkPort.port})" } /** @@ -347,4 +471,39 @@ class NetworkEndpoint private constructor( fun port(): Int { return networkPort.port } + + /** + * 将网络地址和端口转换为IPv4字节数组 + * + * 该函数将当前对象的网络地址转换为IPv4字节数组,并与端口字节数组合并, + * 生成一个包含6个字节的数组,其中前4个字节为IPv4地址,后2个字节为端口号 + * + * @return ByteArray 包含6个字节的数组,前4个字节为IPv4地址,后2个字节为端口号 + */ + fun toIpv4ByteArray(): ByteArray { + val ipv4ByteArray = networkAddress.toIpv4ByteArray() + val portByteArray = networkPort.toByteArray() + // 构建包含IPv4地址和端口的6字节数组 + val byteArray = ByteArray(6) { + if (it < 4) { + ipv4ByteArray[it] + } else { + portByteArray[it - 4] + } + } + return byteArray + } + + /** + * 将IPv4地址和端口信息写入字节缓冲区 + * + * 该函数依次将网络地址的IPv4表示和网络端口写入到指定的字节缓冲区中 + * + * @param byteBuffer 要写入数据的目标字节缓冲区 + */ + fun writeIpv4toByteBuffer(byteBuffer: ByteBuffer): ByteBuffer { + networkAddress.writeIpv4ToByteBuffer(byteBuffer) + networkPort.writeToByteBuffer(byteBuffer) + return byteBuffer + } } diff --git a/src/main/kotlin/com/mingliqiye/utils/uuid/UUID.kt b/src/main/kotlin/com/mingliqiye/utils/uuid/UUID.kt index e3d56bf..e4429ef 100644 --- a/src/main/kotlin/com/mingliqiye/utils/uuid/UUID.kt +++ b/src/main/kotlin/com/mingliqiye/utils/uuid/UUID.kt @@ -1,5 +1,5 @@ /* - * Copyright 2025 mingliqiye + * Copyright 2026 mingliqiye * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile UUID.kt - * LastUpdate 2025-09-21 21:53:40 + * LastUpdate 2026-01-06 12:55:04 * UpdateUser MingLiPro */ @@ -234,6 +234,19 @@ class UUID : Serializable { return UUID(msb, lsb) } + /** + * 从ByteBuffer创建UUID对象 + * + * @param byteBuffer 包含UUID字节数据的ByteBuffer对象,必须包含至少16个字节的数据 + * @return 从ByteBuffer中读取的16个字节创建的UUID对象 + */ + @JvmStatic + fun of(byteBuffer: ByteBuffer): UUID { + val byte = ByteArray(16) + byteBuffer.get(byte) + return UUID(byte) + } + /** * 根据 MySQL UUID 字节数组创建 UUID 实例。 * @@ -296,7 +309,6 @@ class UUID : Serializable { return UUID(this) } - /** * 从字符串解析 UUID 字节数组。 * @@ -422,6 +434,10 @@ class UUID : Serializable { return data } + fun writeToByteBuffer(byteBuffer: ByteBuffer): ByteBuffer { + return byteBuffer.put(data) + } + /** * 返回 UUID 的高位长整型部分。 *