netty--helloword程序
1、使用netty需要使用到下面的java包
netty-all-5.0.0.Alpha2.jar
我们来看下面具体的代码
1. 创建一个ServerBootstrap实例
2. 创建一个EventLoopGroup来处理各种事件,如处理链接请求,发送接收数据等。
3. 定义本地InetSocketAddress( port)好让Server绑定
4. 创建childHandler来处理每一个链接请求
5. 所有准备好之后调用ServerBootstrap.bind()方法绑定Server
package bhz.netty.test; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; public class Server { public static void main(String[] args) throws Exception { //1 第一个线程组 是用于接收Client端连接的 ,第一个线程也叫boss线程组 EventLoopGroup bossGroup = new NioEventLoopGroup(); //2 第二个线程组 是用于实际的业务处理操作的,第二个线程组也叫worker EventLoopGroup workerGroup = new NioEventLoopGroup(); //3 创建一个辅助类Bootstrap,就是对我们的Server进行一系列的配置 ServerBootstrap b = new ServerBootstrap(); //把俩个工作线程组加入到Bootstrap中进来 b.group(bossGroup, workerGroup) //我要指定使用NioServerSocketChannel这种类型的通道,不同的协议这里通道配置不一样 .channel(NioServerSocketChannel.class) //一定要使用 childHandler 去绑定具体的 事件处理器 .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel sc) throws Exception { //通过channel的方法,把ServerHandler添加进去 sc.pipeline().addLast(new ServerHandler()); } }); //还可以配置channel的缓冲区大小等 //绑定指定的端口 进行监听,这里必须调用sync()是异步操作 ChannelFuture f = b.bind(8765).sync(); //Thread.sleep(1000000); //为了让服务器端程序一直运行,不会停止,等价于/Thread.sleep(1000000); f.channel().closeFuture().sync(); bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } }
package bhz.netty.test; /* *注意所以的包都必须是netty的 */ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; import io.netty.util.ReferenceCountUtil; public class ServerHandler extends ChannelHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //do something msg ByteBuf buf = (ByteBuf)msg; byte[] data = new byte[buf.readableBytes()]; buf.readBytes(data); String request = new String(data, "utf-8"); System.out.println("Server: " + request); //写给客户端 String response = "我是反馈的信息"; ctx.writeAndFlush(Unpooled.copiedBuffer("888".getBytes())).; //.addListener(ChannelFutureListener.CLOSE); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }
客户端对应的代码:
package bhz.netty.test; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; public class Client { public static void main(String[] args) throws Exception { //客户端不需要boss线程组,只需要worker线程组就可以 EventLoopGroup workgroup = new NioEventLoopGroup(); //服务器端对应的ServerBootstrap Bootstrap b = new Bootstrap(); b.group(workgroup) //服务器端对应的是NioServerSocketChannel .channel(NioSocketChannel.class) //服务器端对应的是childhandle .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel sc) throws Exception { sc.pipeline().addLast(new ClientHandler()); } }); //ChannelFuture异步非阻塞的通道 ChannelFuture cf1 = b.connect("127.0.0.1", 8765).sync(); //buf cf1.channel().writeAndFlush(Unpooled.copiedBuffer("777".getBytes())); cf1.channel().closeFuture().sync(); workgroup.shutdownGracefully(); } }
package bhz.netty.test; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; import io.netty.util.ReferenceCountUtil; public class ClientHandler extends ChannelHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { try { //do something msg ByteBuf buf = (ByteBuf)msg; byte[] data = new byte[buf.readableBytes()]; buf.readBytes(data); String request = new String(data, "utf-8"); System.out.println("Client: " + request); } finally { ReferenceCountUtil.release(msg); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }
第二个需要注意的地方
客户端多次调用write函数发送数据,但是最后才调用flush,server端收到的数据如下,server端只会收到一次数据,数据如下
所以在编写程序代码的时候,最好使用writeAndFlush()
第三个需要注意的地方
服务端收到客户端发送的数据,需要把数据回复给客户端,这里可以添加一个监听,监听客户端是否收到了服务器发送的数据,监听到客户端收到数据之后,服务端会主动关闭客户端和服务器端建立的连接,客户端的连接就没有了,但是服务器一直还运行
上述代码还有一个更简单的书写形式
在服务端的ServerHandle代码中添加
注意上面的操作是放在服务端中,如果放在客户端中,客户端把数据发送给服务器之后,如果客户端就调用上面的函数,当监听到服务器收到了客户端的数据之后,客户端就主动把连接关闭掉了,就会导致服务器端回复给客户端的数据客户端无法获取到。
posted on 2018-02-09 15:18 luzhouxiaoshuai 阅读(258) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!