Netty 框架实现 C/S 结构网络程序处理 TCP 半包问题
使用 Netty 框架实现一个简单的 C/S 结构的网络程序处理 tcp 半包问题(粘包、拆包),运行结果改成客户端输出
以下是使用 Netty 框架实现一个简单的 C/S 结构的网络程序处理 tcp 半包问题(粘包、拆包)的完整代码,其中客户端输出已修改:
服务端代码:
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.util.CharsetUtil;
public class Server {
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 使用 DelimiterBasedFrameDecoder 处理半包问题
pipeline.addLast(new DelimiterBasedFrameDecoder(1024, Delimiters.lineDelimiter()));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast(new ServerHandler());
}
});
ChannelFuture channelFuture = serverBootstrap.bind(8888).sync();
System.out.println("Server started...");
channelFuture.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
private static class ServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
String request = (String) msg;
System.out.println("Server received: '" + request + "'");
String response = "Hello," + request + ",fromServer.";
ByteBuf encoded = ctx.alloc().buffer(4 * response.length());
encoded.writeBytes(response.getBytes());
ctx.write(encoded);
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
}
### 客户端代码:
```java
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.util.CharsetUtil;
public class Client {
public static void main(String[] args) throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 使用 DelimiterBasedFrameDecoder 处理半包问题
pipeline.addLast(new DelimiterBasedFrameDecoder(1024, Delimiters.lineDelimiter()));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast(new ClientHandler());
}
});
ChannelFuture channelFuture = bootstrap.connect("localhost", 8888).sync();
System.out.println("Client active...");
channelFuture.channel().writeAndFlush("Hello,Netty");
channelFuture.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
}
private static class ClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
String response = (String) msg;
System.out.println("Client received: '" + response + "'");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
}
运行结果:
客户端输出:
Client active...
Client received: 'Hello,Hello,Netty,fromServer.'
服务器端输出:
Server started...
Server received: 'Hello,Netty'
代码说明:
- 代码中使用了
DelimiterBasedFrameDecoder来解决 TCP 半包问题,通过设置Delimiters.lineDelimiter()来指定消息的结束符(换行符)。 - 客户端发送消息时,使用了
channelFuture.channel().writeAndFlush()方法将消息写入网络。 - 服务器接收消息后,使用
System.out.println()打印到控制台。 - 代码中使用了
StringDecoder将接收到的字节流解码为字符串,方便处理。
总结:
这只是一个简单的使用 Netty 框架实现 C/S 结构网络程序的示例,通过使用 DelimiterBasedFrameDecoder 可以有效地解决 TCP 半包问题。实际应用中,可能需要根据具体需求选择不同的编码解码器和消息格式。
原文地址: https://www.cveoy.top/t/topic/j59u 著作权归作者所有。请勿转载和采集!