zoukankan      html  css  js  c++  java
  • [转]Netty入门(最简单的Netty客户端/服务器程序)

     Java中的NIO是一种解决阻塞式IO问题的基本技术,但是NIO的编写对java程序员是有比较高的要求的。那么Netty就是一种简化操作的一个成熟的网络IO编程框架。这里简单介绍一个程序,代码是《netty in action》里面的,不过那个里面的实例有点问题,反正我没有跑成功,修改后成功。直接上代码:


     一、服务器编写

      Server代码,监听连接

    复制代码
     1 package com.gerry.netty.server;
     2 
     3 import io.netty.bootstrap.ServerBootstrap;
     4 import io.netty.channel.ChannelFuture;
     5 import io.netty.channel.ChannelInitializer;
     6 import io.netty.channel.EventLoopGroup;
     7 import io.netty.channel.nio.NioEventLoopGroup;
     8 import io.netty.channel.socket.SocketChannel;
     9 import io.netty.channel.socket.nio.NioServerSocketChannel;
    10 
    11 public class EchoServer {
    12     private final int port;
    13 
    14     public EchoServer(int port) {
    15         this.port = port;
    16     }
    17 
    18     public void start() throws Exception {
    19         EventLoopGroup group = new NioEventLoopGroup();
    20         try {
    21             ServerBootstrap sb = new ServerBootstrap();
    22             sb.group(group) // 绑定线程池
    23                     .channel(NioServerSocketChannel.class) // 指定使用的channel
    24                     .localAddress(this.port)// 绑定监听端口
    25                     .childHandler(new ChannelInitializer<SocketChannel>() { // 绑定客户端连接时候触发操作
    26 
    27                                 @Override
    28                                 protected void initChannel(SocketChannel ch) throws Exception {
    29                                     System.out.println("connected...; Client:" + ch.remoteAddress());
    30                                     ch.pipeline().addLast(new EchoServerHandler()); // 客户端触发操作
    31                                 }
    32                             });
    33             ChannelFuture cf = sb.bind().sync(); // 服务器异步创建绑定
    34             System.out.println(EchoServer.class + " started and listen on " + cf.channel().localAddress());
    35             cf.channel().closeFuture().sync(); // 关闭服务器通道
    36         } finally {
    37             group.shutdownGracefully().sync(); // 释放线程池资源
    38         }
    39     }
    40 
    41     public static void main(String[] args) throws Exception {
    42         new EchoServer(65535).start(); // 启动
    43     }
    44 }
    复制代码

       具体的处理客户端连接的代码

    复制代码
     1 package com.gerry.netty.server;
     2 
     3 import io.netty.buffer.Unpooled;
     4 import io.netty.channel.ChannelFutureListener;
     5 import io.netty.channel.ChannelHandlerContext;
     6 import io.netty.channel.ChannelInboundHandlerAdapter;
     7 
     8 public class EchoServerHandler extends ChannelInboundHandlerAdapter {
     9     @Override
    10     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    11         System.out.println("server channelRead...; received:" + msg);
    12         ctx.write(msg);
    13     }
    14 
    15     @Override
    16     public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    17         System.out.println("server channelReadComplete..");
    18         // 第一种方法:写一个空的buf,并刷新写出区域。完成后关闭sock channel连接。
    19         ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
    20         //ctx.flush(); // 第二种方法:在client端关闭channel连接,这样的话,会触发两次channelReadComplete方法。
    21         //ctx.flush().close().sync(); // 第三种:改成这种写法也可以,但是这中写法,没有第一种方法的好。
    22     }
    23 
    24     @Override
    25     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    26         System.out.println("server occur exception:" + cause.getMessage());
    27         cause.printStackTrace();
    28         ctx.close(); // 关闭发生异常的连接
    29     }
    30 }
    复制代码

     二、客户端编写

      具体的连接代码

    复制代码
     1 package com.gerry.netty.client;
     2 
     3 import io.netty.bootstrap.Bootstrap;
     4 import io.netty.channel.ChannelFuture;
     5 import io.netty.channel.ChannelInitializer;
     6 import io.netty.channel.EventLoopGroup;
     7 import io.netty.channel.nio.NioEventLoopGroup;
     8 import io.netty.channel.socket.SocketChannel;
     9 import io.netty.channel.socket.nio.NioSocketChannel;
    10 
    11 import java.net.InetSocketAddress;
    12 
    13 public class EchoClient {
    14     private final String host;
    15     private final int port;
    16 
    17     public EchoClient() {
    18         this(0);
    19     }
    20 
    21     public EchoClient(int port) {
    22         this("localhost", port);
    23     }
    24 
    25     public EchoClient(String host, int port) {
    26         this.host = host;
    27         this.port = port;
    28     }
    29 
    30     public void start() throws Exception {
    31         EventLoopGroup group = new NioEventLoopGroup();
    32         try {
    33             Bootstrap b = new Bootstrap();
    34             b.group(group) // 注册线程池
    35                     .channel(NioSocketChannel.class) // 使用NioSocketChannel来作为连接用的channel类
    36                     .remoteAddress(new InetSocketAddress(this.host, this.port)) // 绑定连接端口和host信息
    37                     .handler(new ChannelInitializer<SocketChannel>() { // 绑定连接初始化器
    38                                 @Override
    39                                 protected void initChannel(SocketChannel ch) throws Exception {
    40                                     System.out.println("connected...");
    41                                     ch.pipeline().addLast(new EchoClientHandler());
    42                                 }
    43                             });
    44             System.out.println("created..");
    45 
    46             ChannelFuture cf = b.connect().sync(); // 异步连接服务器
    47             System.out.println("connected..."); // 连接完成
    48 
    49             cf.channel().closeFuture().sync(); // 异步等待关闭连接channel
    50             System.out.println("closed.."); // 关闭完成
    51         } finally {
    52             group.shutdownGracefully().sync(); // 释放线程池资源
    53         }
    54     }
    55 
    56     public static void main(String[] args) throws Exception {
    57         new EchoClient("127.0.0.1", 65535).start(); // 连接127.0.0.1/65535,并启动
    58     }
    59 }
    复制代码

      连接成功后,具体的通信代码

    复制代码
     1 package com.gerry.netty.client;
     2 
     3 import java.nio.charset.Charset;
     4 
     5 import io.netty.buffer.ByteBuf;
     6 import io.netty.buffer.ByteBufUtil;
     7 import io.netty.buffer.Unpooled;
     8 import io.netty.channel.ChannelHandlerContext;
     9 import io.netty.channel.SimpleChannelInboundHandler;
    10 import io.netty.util.CharsetUtil;
    11 
    12 public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
    13 
    14     @Override
    15     public void channelActive(ChannelHandlerContext ctx) throws Exception {
    16         System.out.println("client channelActive..");
    17         ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8)); // 必须有flush
    18 
    19         // 必须存在flush
    20         // ctx.write(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8));
    21         // ctx.flush();
    22     }
    23 
    24     @Override
    25     protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
    26         System.out.println("client channelRead..");
    27         ByteBuf buf = msg.readBytes(msg.readableBytes());
    28         System.out.println("Client received:" + ByteBufUtil.hexDump(buf) + "; The value is:" + buf.toString(Charset.forName("utf-8")));
    29         //ctx.channel().close().sync();// client关闭channel连接
    30     }
    31 
    32     @Override
    33     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    34         cause.printStackTrace();
    35         ctx.close();
    36     }
    37 
    38 }
    复制代码

     三、结果

      先运行server,在运行client即可。

     

    转载链接:http://www.cnblogs.com/liuming1992/p/4758532.html

    以上netty使用的版本

    <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
    <dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.6.Final</version>
    </dependency>

  • 相关阅读:
    Hadoop分布式文件系统:架构和设计
    分布式设计学习资料
    codeforces上一道贪心算法题
    优先队列实现n路归并算法O(n * lgK)
    LINUX 暂停、继续进程
    重叠(Overlapped)IO模型
    WSAEventSelect模型
    WSAEventSelect模型 应用实例,重写TCP服务器实例
    选择模型2
    第四章 数据抽象 《C++编程思想》
  • 原文地址:https://www.cnblogs.com/luohengstudy/p/8032007.html
Copyright © 2011-2022 走看看