业务背景
在项目中需要用到即时通讯业务,比如聊天应用或实时通知应用。在这种应用中,客户端和服务器之间需要保持持久的连接,以实现实时消息的传递。
具体来说,在聊天应用中,当用户登录应用时,客户端会与服务器建立一个长连接。通过这个长连接,服务器可以向客户端推送新消息,并且客户端也可以发送消息给其他用户或群组。这种实时的双向通信需要使用长连接来实现。
使用Netty实现长连接可以提供以下优势:
使用Netty实现长连接的聊天应用可以满足用户对实时通信的需求,提供即时的消息交互和通知功能。通过长连接,用户可以接收到其他用户发送的消息,并且可以实时地与其他用户进行沟通和交流。这样的应用场景包括在线客服系统、社交网络应用、团队协作工具等。
netty实现聊天的逻辑
Netty实现简单聊天逻辑的Java代码示例:
public class NettyServer {
private static final int PORT = 8888;
public static void main(String[] args) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap()
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(new ChatServerHandler());
}
});
ChannelFuture future = bootstrap.bind(PORT).sync();
System.out.println("Server started on port " + PORT);
future.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
@ChannelHandler.Sharable
public class ChatServerHandler extends SimpleChannelInboundHandler {
private static final ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
Channel incoming = ctx.channel();
System.out.println("Client connected: " + incoming.remoteAddress());
channelGroup.add(incoming);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
Channel incoming = ctx.channel();
System.out.println("Client disconnected: " + incoming.remoteAddress());
channelGroup.remove(incoming);
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
Channel incoming = ctx.channel();
System.out.println("Received message from " + incoming.remoteAddress() + ": " + msg);
// 广播消息给所有客户端
for (Channel channel : channelGroup) {
if (channel != incoming) {
channel.writeAndFlush("[" + incoming.remoteAddress() + "]: " + msg + "\n");
} else {
channel.writeAndFlush("[You]: " + msg + "\n");
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
Channel incoming = ctx.channel();
System.err.println("Client " + incoming.remoteAddress() + " encountered an error.");
cause.printStackTrace();
ctx.close();
}
}
public class NettyClient {
private static final String HOST = "localhost";
private static final int PORT = 8888;
public static void main(String[] args) throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap()
.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(new ChatClientHandler());
}
});
Channel channel = bootstrap.connect(HOST, PORT).sync().channel();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String msg = reader.readLine();
if (msg == null || "quit".equalsIgnoreCase(msg)) {
break;
}
channel.writeAndFlush(msg + "\n");
}
} finally {
group.shutdownGracefully();
}
}
}
@ChannelHandler.Sharable
public class ChatClientHandler extends SimpleChannelInboundHandler {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(msg);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
Netty服务器和客户端都通过\n
作为分隔符进行消息的解码和编码。当服务器接收到一个消息时,它会将消息广播给所有连接的客户端。客户端可以通过控制台输入消息,并将其发送到服务器。