两个星期的努力netty ndk方式.成功加载openssl工程

本文分享了GMSSl库通过NDK方式进行调用的成功案例,实现了SM2-WITH-SM4-SHA256的CipherSuite,为密码学应用提供了新的可能性。

应该庆祝下gmssl可以使用ndk的方式调用了,SM2-WITH-SM4-SHA256的CipherSuite.

有图有真相

@Test @Timeout(value = 10, unit = TimeUnit.SECONDS) void testResponseTimeout() throws InterruptedException { // 定义一个不响应的服务器(覆盖createChannelInitializer) TcpServer nonResponsiveServer = new TcpServer() { @Override protected ChannelInitializer createChannelInitializer() { return new ChannelInitializer() { @Override protected void initChannel(SocketChannel ch) { // 仅保留解码器,移除业务处理器和编码器(不返回响应) ch.pipeline().addLast( new LengthFieldFrameDecoder(), new JsonRequestDecoder() ); } }; } }; // 启动服务器线程(处理InterruptedException) Thread nonResponsiveServerThread = new Thread(() -> { try { nonResponsiveServer.start(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 恢复中断状态 LOG.error("服务器启动被中断", e); } }); nonResponsiveServerThread.start(); // 等待服务器启动(根据实际情况调整等待时间) Thread.sleep(3000); // 客户端连接并发送请求(验证超时) TcpClient client = new TcpClient("127.0.0.1", 8080); client.connect(); GreetRequest request = new GreetRequest(); request.setName("TimeoutUser"); GreetResponse response = client.sendRequest(request); assertThat(response).isNull(); // 预期超时返回null // 清理资源 client.shutdown(); nonResponsiveServer.shutdown(); nonResponsiveServerThread.join(3000); } @Test @Timeout(value = 10, unit = TimeUnit.SECONDS) // 防止测试卡住 void testNormalCommunication() throws InterruptedException { // 初始化客户端 TcpClient client = new TcpClient("127.0.0.1", TEST_PORT); client.connect(); // 构造请求 GreetRequest request = new GreetRequest(); request.setName("TestUser"); // 发送请求并等待响应 GreetResponse response = client.sendRequest(request); // 验证响应 assertThat(response).isNotNull(); assertThat(response.getMessage()).isEqualTo("Hello, TestUser!"); // 关闭客户端 client.shutdown(); }报错Exception in thread "Thread-3" java.net.BindException: Address already in use: bind at sun.nio.ch.Net.bind0(Native Method) at sun.nio.ch.Net.bind(Net.java:461) at sun.nio.ch.Net.bind(Net.java:453) at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:222) at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:148) at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:434) at io.netty.channel.DefaultChannelPipeline$HeadContext.bind(DefaultChannelPipeline.java:1353) at io.netty.channel.AbstractChannelHandlerContext.invokeBind(AbstractChannelHandlerContext.java:492) at io.netty.channel.AbstractChannelHandlerContext.bind(AbstractChannelHandlerContext.java:471) at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:994) at io.netty.channel.Channel.bind(Channel.java:302) at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:380) at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:148) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute$$$capture(AbstractEventExecutor.java:141) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java) at --- Async.Stack.Trace --- (captured by IntelliJ IDEA debugger) at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java) at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:907) at io.netty.util.concurrent.SingleThreadEventExecutor.execute0(SingleThreadEventExecutor.java:873) at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:863) at io.netty.bootstrap.AbstractBootstrap.doBind0(AbstractBootstrap.java:376) at io.netty.bootstrap.AbstractBootstrap.access$000(AbstractBootstrap.java:54) at io.netty.bootstrap.AbstractBootstrap$1.operationComplete(AbstractBootstrap.java:315) at io.netty.bootstrap.AbstractBootstrap$1.operationComplete(AbstractBootstrap.java:302) at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:603) at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:570) at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:505) at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:649) at io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:638) at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:118) at io.netty.channel.DefaultChannelPromise.trySuccess(DefaultChannelPromise.java:84) at io.netty.channel.AbstractChannel$AbstractUnsafe.safeSetSuccess(AbstractChannel.java:861) at io.netty.channel.AbstractChannel$AbstractUnsafe$2.operationComplete(AbstractChannel.java:385) at io.netty.channel.AbstractChannel$AbstractUnsafe$2.operationComplete(AbstractChannel.java:374) at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:603) at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:570) at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:505) at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:649) at io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:638) at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:110) at io.netty.channel.DefaultChannelPromise.setSuccess(DefaultChannelPromise.java:78) at io.netty.channel.DefaultChannelPromise.setSuccess(DefaultChannelPromise.java:73) at io.netty.channel.nio.AbstractNioChannel.lambda$doRegister$0(AbstractNioChannel.java:465) at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:603) at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:570) at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:505) at io.netty.util.concurrent.DefaultPromise.addListener(DefaultPromise.java:198) at io.netty.util.concurrent.DefaultPromise.addListener(DefaultPromise.java:36) at io.netty.channel.nio.AbstractNioChannel.doRegister(AbstractNioChannel.java:462) at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:408) at io.netty.channel.AbstractChannel$AbstractUnsafe.access$300(AbstractChannel.java:288) at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:352) at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:148) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute$$$capture(AbstractEventExecutor.java:141) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java) at --- Async.Stack.Trace --- (captured by IntelliJ IDEA debugger) at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java) at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:907) at io.netty.util.concurrent.SingleThreadEventExecutor.execute0(SingleThreadEventExecutor.java:873) at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:863) at io.netty.channel.AbstractChannel$AbstractUnsafe.register(AbstractChannel.java:349) at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:119) at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:113) at io.netty.channel.MultithreadEventLoopGroup.register(MultithreadEventLoopGroup.java:86) at io.netty.bootstrap.AbstractBootstrap.initAndRegister(AbstractBootstrap.java:339) at io.netty.bootstrap.AbstractBootstrap.doBind(AbstractBootstrap.java:288) at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:284) at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:262) at server.TcpServer.start(TcpServer.java:75) at TcpServerClientTest.lambda$startServer$0(TcpServerClientTest.java:45) at java.lang.Thread.run(Thread.java:750) Suppressed: java.util.concurrent.CompletionException: Rethrowing promise failure cause at io.netty.util.concurrent.DefaultPromise.rethrowIfFailed(DefaultPromise.java:685) at io.netty.util.concurrent.DefaultPromise.sync(DefaultPromise.java:419) at io.netty.channel.DefaultChannelPromise.sync(DefaultChannelPromise.java:119) at io.netty.channel.DefaultChannelPromise.sync(DefaultChannelPromise.java:30) ... 3 more Exception in thread “Thread-4” java.net.BindException: Address already in use: bind at sun.nio.ch.Net.bind0(Native Method) at sun.nio.ch.Net.bind(Net.java:461) at sun.nio.ch.Net.bind(Net.java:453) at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:222) at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:148) at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:434) at io.netty.channel.DefaultChannelPipeline$HeadContext.bind(DefaultChannelPipeline.java:1353) at io.netty.channel.AbstractChannelHandlerContext.invokeBind(AbstractChannelHandlerContext.java:492) at io.netty.channel.AbstractChannelHandlerContext.bind(AbstractChannelHandlerContext.java:471) at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:994) at io.netty.channel.Channel.bind(Channel.java:302) at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:380) at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:148) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute$$$capture(AbstractEventExecutor.java:141) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java) at — Async.Stack.Trace — (captured by IntelliJ IDEA debugger) at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java) at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:907) at io.netty.util.concurrent.SingleThreadEventExecutor.execute0(SingleThreadEventExecutor.java:873) at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:863) at io.netty.bootstrap.AbstractBootstrap.doBind0(AbstractBootstrap.java:376) at io.netty.bootstrap.AbstractBootstrap.access$000(AbstractBootstrap.java:54) at io.netty.bootstrap.AbstractBootstrap$1.operationComplete(AbstractBootstrap.java:315) at io.netty.bootstrap.AbstractBootstrap$1.operationComplete(AbstractBootstrap.java:302) at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:603) at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:570) at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:505) at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:649) at io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:638) at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:118) at io.netty.channel.DefaultChannelPromise.trySuccess(DefaultChannelPromise.java:84) at io.netty.channel.AbstractChannel$AbstractUnsafe.safeSetSuccess(AbstractChannel.java:861) at io.netty.channel.AbstractChannel$AbstractUnsafe$2.operationComplete(AbstractChannel.java:385) at io.netty.channel.AbstractChannel$AbstractUnsafe$2.operationComplete(AbstractChannel.java:374) at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:603) at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:570) at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:505) at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:649) at io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:638) at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:110) at io.netty.channel.DefaultChannelPromise.setSuccess(DefaultChannelPromise.java:78) at io.netty.channel.DefaultChannelPromise.setSuccess(DefaultChannelPromise.java:73) at io.netty.channel.nio.AbstractNioChannel.lambda$doRegister$0(AbstractNioChannel.java:465) at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:603) at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:570) at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:505) at io.netty.util.concurrent.DefaultPromise.addListener(DefaultPromise.java:198) at io.netty.util.concurrent.DefaultPromise.addListener(DefaultPromise.java:36) at io.netty.channel.nio.AbstractNioChannel.doRegister(AbstractNioChannel.java:462) at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:408) at io.netty.channel.AbstractChannel$AbstractUnsafe.access$300(AbstractChannel.java:288) at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:352) at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:148) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute$$$capture(AbstractEventExecutor.java:141) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java) at — Async.Stack.Trace — (captured by IntelliJ IDEA debugger) at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java) at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:907) at io.netty.util.concurrent.SingleThreadEventExecutor.execute0(SingleThreadEventExecutor.java:873) at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:863) at io.netty.channel.AbstractChannel$AbstractUnsafe.register(AbstractChannel.java:349) at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:119) at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:113) at io.netty.channel.MultithreadEventLoopGroup.register(MultithreadEventLoopGroup.java:86) at io.netty.bootstrap.AbstractBootstrap.initAndRegister(AbstractBootstrap.java:339) at io.netty.bootstrap.AbstractBootstrap.doBind(AbstractBootstrap.java:288) at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:284) at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:262) at server.TcpServer.start(TcpServer.java:75) at TcpServerClientTest.lambda$testResponseTimeout$1(TcpServerClientTest.java:119) at java.lang.Thread.run(Thread.java:750) Suppressed: java.util.concurrent.CompletionException: Rethrowing promise failure cause at io.netty.util.concurrent.DefaultPromise.rethrowIfFailed(DefaultPromise.java:685) at io.netty.util.concurrent.DefaultPromise.sync(DefaultPromise.java:419) at io.netty.channel.DefaultChannelPromise.sync(DefaultChannelPromise.java:119) at io.netty.channel.DefaultChannelPromise.sync(DefaultChannelPromise.java:30) … 3 more [main] INFO client.TcpClient - 客户端连接成功,目标地址:127.0.0.1:8080 Duplicate field name “$hits$” with signature “[I” in class file io/netty/buffer/AllocateChunkEvent JfrClassAdapter: unable to create InstanceKlass Duplicate field name “$hits$” with signature “[I” in class file io/netty/buffer/AllocateBufferEvent JfrClassAdapter: unable to create InstanceKlass Duplicate field name “$hits$” with signature “[I” in class file io/netty/buffer/FreeBufferEvent JfrClassAdapter: unable to create InstanceKlass [main] INFO server.TcpServer - 服务器已关闭 org.opentest4j.AssertionFailedError: expected: null but was: model.GreetResponse@e7529ac 预期:null 实际:model.GreetResponse@e7529ac;Exception in thread “Thread-5” java.net.BindException: Address already in use: bind at sun.nio.ch.Net.bind0(Native Method) at sun.nio.ch.Net.bind(Net.java:461) at sun.nio.ch.Net.bind(Net.java:453) at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:222) at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:148) at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:434) at io.netty.channel.DefaultChannelPipeline$HeadContext.bind(DefaultChannelPipeline.java:1353) at io.netty.channel.AbstractChannelHandlerContext.invokeBind(AbstractChannelHandlerContext.java:492) at io.netty.channel.AbstractChannelHandlerContext.bind(AbstractChannelHandlerContext.java:471) at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:994) at io.netty.channel.Channel.bind(Channel.java:302) at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:380) at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:148) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute$$$capture(AbstractEventExecutor.java:141) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java) at — Async.Stack.Trace — (captured by IntelliJ IDEA debugger) at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java) at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:907) at io.netty.util.concurrent.SingleThreadEventExecutor.execute0(SingleThreadEventExecutor.java:873) at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:863) at io.netty.bootstrap.AbstractBootstrap.doBind0(AbstractBootstrap.java:376) at io.netty.bootstrap.AbstractBootstrap.access$000(AbstractBootstrap.java:54) at io.netty.bootstrap.AbstractBootstrap$1.operationComplete(AbstractBootstrap.java:315) at io.netty.bootstrap.AbstractBootstrap$1.operationComplete(AbstractBootstrap.java:302) at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:603) at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:570) at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:505) at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:649) at io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:638) at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:118) at io.netty.channel.DefaultChannelPromise.trySuccess(DefaultChannelPromise.java:84) at io.netty.channel.AbstractChannel$AbstractUnsafe.safeSetSuccess(AbstractChannel.java:861) at io.netty.channel.AbstractChannel$AbstractUnsafe$2.operationComplete(AbstractChannel.java:385) at io.netty.channel.AbstractChannel$AbstractUnsafe$2.operationComplete(AbstractChannel.java:374) at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:603) at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:570) at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:505) at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:649) at io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:638) at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:110) at io.netty.channel.DefaultChannelPromise.setSuccess(DefaultChannelPromise.java:78) at io.netty.channel.DefaultChannelPromise.setSuccess(DefaultChannelPromise.java:73) at io.netty.channel.nio.AbstractNioChannel.lambda$doRegister$0(AbstractNioChannel.java:465) at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:603) at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:570) at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:505) at io.netty.util.concurrent.DefaultPromise.addListener(DefaultPromise.java:198) at io.netty.util.concurrent.DefaultPromise.addListener(DefaultPromise.java:36) at io.netty.channel.nio.AbstractNioChannel.doRegister(AbstractNioChannel.java:462) at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:408) at io.netty.channel.AbstractChannel$AbstractUnsafe.access$300(AbstractChannel.java:288) at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:352) at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:148) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute$$$capture(AbstractEventExecutor.java:141) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java) at — Async.Stack.Trace — (captured by IntelliJ IDEA debugger) at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java) at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:907) at io.netty.util.concurrent.SingleThreadEventExecutor.execute0(SingleThreadEventExecutor.java:873) at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:863) at io.netty.channel.AbstractChannel$AbstractUnsafe.register(AbstractChannel.java:349) at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:119) at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:113) at io.netty.channel.MultithreadEventLoopGroup.register(MultithreadEventLoopGroup.java:86) at io.netty.bootstrap.AbstractBootstrap.initAndRegister(AbstractBootstrap.java:339) at io.netty.bootstrap.AbstractBootstrap.doBind(AbstractBootstrap.java:288) at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:284) at io.netty.bootstrap.AbstractBootstrap.bind(AbstractBootstrap.java:262) at server.TcpServer.start(TcpServer.java:75) at TcpServerClientTest.lambda$startServer$0(TcpServerClientTest.java:45) at java.lang.Thread.run(Thread.java:750) Suppressed: java.util.concurrent.CompletionException: Rethrowing promise failure cause at io.netty.util.concurrent.DefaultPromise.rethrowIfFailed(DefaultPromise.java:685) at io.netty.util.concurrent.DefaultPromise.sync(DefaultPromise.java:419) at io.netty.channel.DefaultChannelPromise.sync(DefaultChannelPromise.java:119) at io.netty.channel.DefaultChannelPromise.sync(DefaultChannelPromise.java:30) … 3 more [main] INFO server.TcpServer - 服务器已关闭 [main] INFO client.TcpClient - 客户端连接成功,目标地址:127.0.0.1:8080 [main] INFO client.TcpClient - 客户端已关闭 [main] INFO server.TcpServer - 服务器已关闭 org.opentest4j.AssertionFailedError: Expecting value to be true but was false 预期:true 实际:false 请分析原因并尝试解决
最新发布
08-23
<think>我们遇到了多个问题,包括端口绑定冲突(BindException: Address already in in use)、Netty内部日志警告(Duplicate field name "$hits$")以及测试断言失败(预期为null但实际收到响应,以及预期为true但实际为false)。下面逐一分析: 1. **端口绑定冲突(BindException)**: 错误信息显示多个线程尝试绑定同一个端口(如8080)时失败,因为端口已被占用。在测试中,我们启动了多个服务器(例如在`testResponseTimeout`和`testNormalCommunication`中),它们可能尝试绑定到同一个端口。另外,由于测试是并行运行或前一个测试没有正确释放端口,也会导致此问题。 解决方案: - 确保每个测试使用不同的端口。 - 确保在测试结束后正确关闭服务器并释放端口。在测试方法中,我们使用了`shutdown`方法,但需要确保服务器关闭操作完成后再进行下一个测试(例如使用`nonResponsiveServerThread.join(3000)`等待线程结束,但可能不够,因为关闭操作是异步的)。 - 在测试中,我们可以使用随机端口(例如端口0,由系统分配)或者为每个测试指定不同的固定端口(如8080, 8081等)。但随机端口更可靠。 2. **Netty内部日志警告(Duplicate field name "$hits$")**: 这些警告来自Netty内部,可能是由于Netty的某些类被多个类加载加载,或者某些工具(如JFR)尝试重新定义类导致的。这通常不会影响功能,但可以尝试升级Netty版本或忽略这些警告。 3. **测试断言失败**: - 在`testResponseTimeout`中,我们预期服务器不响应,因此`response`应该为null。但实际收到了一个非空的`GreetResponse`对象。这可能是因为服务器没有按照预期配置(移除业务处理器和编码器)?或者测试代码中实际启动的服务器并不是我们覆盖的那个?另外,端口冲突也可能导致测试环境混乱。 - 另一个测试中预期为true但实际为false,具体原因需要看代码,但同样可能是环境问题。 具体解决步骤: 针对端口冲突: - 在测试中,我们可以让服务器绑定到随机端口(端口0),然后获取实际绑定的端口,再让客户端连接这个端口。 - 或者,在每个测试方法中,使用不同的固定端口(例如8080,8081,8082等),并确保测试是顺序执行的(使用`@Order`注解或调整测试顺序)。 由于我们无法在测试中直接使用端口0(因为需要告知客户端端口号),我们可以这样做: 1. 在服务器启动前,创建一个`ServerSocket`并绑定到端口0,然后立即关闭它,这样系统会分配一个空闲端口,我们获取这个端口号,然后让服务器和客户端都使用这个端口。 2. 或者,使用JUnit的`@BeforeEach`和`@AfterEach`来管理服务器和端口,确保每个测试使用独立端口。 但是,在Netty中,我们可以直接绑定到端口0,然后获取绑定的实际端口。例如: ```java ServerBootstrap b = new ServerBootstrap(); // ... 配置b ChannelFuture future = b.bind(0).sync(); int port = ((InetSocketAddress) future.channel().localAddress()).getPort(); ``` 然后,将这个端口传递给客户端。 由于测试代码结构,我们需要调整服务器启动方式,使其能够返回实际绑定的端口。然后,在客户端连接时使用这个端口。 另外,注意在测试结束后正确关闭服务器,并等待关闭完成(使用`sync()`或`await()`)。 针对`testResponseTimeout`测试失败(预期null但实际有响应): 我们创建了一个不响应服务器(移除了业务处理器和编码器),但为什么客户端还是收到了响应?可能的原因有: - 服务器配置错误:我们覆盖了`createChannelInitializer`,但可能这个覆盖并没有被实际使用?需要检查服务器启动时是否使用了这个初始器。 - 由于端口冲突,测试实际连接到了之前未关闭的服务器(正常响应的那个)?所以确保端口不冲突和正确关闭服务器很重要。 针对另一个测试(预期true但实际false): 需要具体看是哪个测试,但同样可能是环境问题。 建议的修改: 1. 重构TcpServer,使其可以绑定到指定端口(包括0)并返回实际绑定的端口。 2. 在测试中,每个服务器都绑定到0端口,然后获取实际端口,并确保客户端连接这个端口。 3. 确保每个测试都正确关闭服务器,并等待关闭完成(使用`ChannelFuture`的`sync`或`await`)。 由于代码较长,这里只给出关键修改思路: 在TcpServer类中: - 修改`start`方法,允许传入端口(可以传入0),然后绑定到这个端口。 - 在绑定后,获取实际绑定的端口并返回。 ```java public int start(int port) throws InterruptedException { // 配置ServerBootstrap... ChannelFuture future = bootstrap.bind(port).sync(); // 获取实际绑定的端口 this.port = ((InetSocketAddress) future.channel().localAddress()).getPort(); // 记录日志 return this.port; } ``` 在测试中: - 每个测试启动自己的服务器,使用端口0,并获取实际端口。 - 客户端连接这个实际端口。 另外,在测试中,要确保服务器关闭后端口被释放。在`shutdown`方法中,我们应确保关闭操作完成: ```java public void shutdown() throws InterruptedException { if (bossGroup != null) { bossGroup.shutdownGracefully().sync(); } if (workerGroup != null) { workerGroup.shutdownGracefully().sync(); } } ``` 使用`sync()`确保关闭完成。 同时,在测试代码中,要确保在测试方法结束时关闭服务器并等待关闭完成。 由于时间关系,这里不展开所有代码修改。但按照上述思路,应该可以解决端口冲突问题。 针对不响应服务器的测试,需要再次检查覆盖的`ChannelInitializer`是否正确移除了业务处理器和编码器。另外,确保客户端连接的是这个不响应服务器,而不是其他服务器。 最后,关于Netty的警告,可以尝试升级Netty到最新版本,或者忽略这些警告(因为它们可能只是警告,不影响功能)。 总结修改步骤: 1. 修改TcpServer,使其在绑定端口0时能返回实际端口,并确保关闭方法等待关闭完成。 2. 在测试中,每个测试方法都使用独立的服务器实例,并绑定到端口0,然后使用返回的实际端口创建客户端。 3. 确保每个测试方法在结束时关闭服务器并等待关闭完成(使用`shutdown`方法,并在其中调用`sync`)。 4. 对于不响应服务器的测试,确保其配置正确,并且客户端连接到了正确的服务器。 由于原始代码较长,这里无法提供完整的修改代码,但按照上述思路修改,应该可以解决大部分问题。 如果问题仍然存在,请检查测试代码中是否有多个服务器同时启动(比如在测试类中使用了`@BeforeEach`启动了一个服务器,又在测试方法中启动了一个)?确保测试方法之间不会相互干扰。 另外,注意测试方法执行顺序:默认情况下,JUnit测试方法执行顺序是不确定的,但可以通过`@TestMethodOrder`和`@Order`指定顺序。但最好每个测试都是独立的,使用不同的端口。 由于时间限制,这里只能提供思路,具体实现需要根据项目代码调整。</think>### 问题分析及解决方案 根据错误日志和测试失败信息,主要存在以下问题: 1. **端口冲突(Address already in use)** - 多个测试并行启动服务器时绑定相同端口(8080) - 前一个测试未完全释放端口,后一个测试立即尝试绑定 2. **超时测试失败** - `testResponseTimeout` 预期返回 null 但实际收到响应 - 原因:非响应服务器可能未正确配置,或客户端连接了错误服务器 3. **Netty 内部警告** - `Duplicate field name "$hits$"` 是 Netty 内部 JFR 事件注册问题 - 通常不影响功能,可暂时忽略 --- ### 解决方案 #### 1. 解决端口冲突问题 **修改服务器启动方式:** ```java // 在测试类中定义动态获取空闲端口的方法 private int getAvailablePort() throws IOException { try (ServerSocket socket = new ServerSocket(0)) { return socket.getLocalPort(); } } // 在每个测试中动态分配端口 @Test void testResponseTimeout() throws Exception { int port = getAvailablePort(); // 获取空闲端口 TcpServer nonResponsiveServer = ... // 创建服务器 nonResponsiveServer.start(port); // 使用动态端口启动 TcpClient client = new TcpClient("127.0.0.1", port); // 客户端连接相同端口 // ... 后续测试代码 } ``` #### 2. 修复超时测试 **确保服务器配置正确:** ```java protected ChannelInitializer createChannelInitializer() { return new ChannelInitializer() { @Override protected void initChannel(SocketChannel ch) { // 移除所有处理器(包括解码器) ch.pipeline().clear(); // 添加空处理器防止自动断开 ch.pipeline().addLast(new ChannelInboundHandlerAdapter()); } }; } ``` **增强客户端超时检测:** ```java // 在客户端发送请求方法中添加超时控制 public GreetResponse sendRequest(GreetRequest request) { // 设置响应等待超时(例如3秒) channel.writeAndFlush(request).awaitUninterruptibly(3, TimeUnit.SECONDS); return responseQueue.poll(3, TimeUnit.SECONDS); // 超时返回null } ``` #### 3. 资源释放优化 **确保彻底关闭服务器:** ```java public void shutdown() throws InterruptedException { if (bossGroup != null) { bossGroup.shutdownGracefully().sync(); // 阻塞直到关闭完成 } // 添加端口释放等待 Thread.sleep(500); } ``` #### 4. 测试顺序调整 **添加测试依赖顺序:** ```java @FixMethodOrder(MethodSorters.NAME_ASCENDING) // 按方法名字典序执行 class TcpServerClientTest { @Test void test1_ResponseTimeout() { ... } @Test void test2_NormalCommunication() { ... } } ``` --- ### 验证要点 1. 使用 `netstat -ano | findstr :8080` 确认测试后端口释放 2. 在 `testResponseTimeout` 中添加日志,确认服务器pipeline配置 3. 检查客户端是否连接了正确的动态端口
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值