Netty初探-netty服务端和客户端demo

忘是亡心i 2022-09-25 14:23 377阅读 0赞

通过netty框架实现一个简单的服务端和客户端框架,相比于前面所说的NIO,netty的api使用更加简单灵活,扩展性强。

  • TimeServer

    package com.xpn.netty.netty;

    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 TimeServer {

    1. public void bind(int port) throws InterruptedException {
    2. // 配置NIO线程组
    3. EventLoopGroup bossGroup = new NioEventLoopGroup()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;// 连接线程</span>
    4. EventLoopGroup workerGroup = new NioEventLoopGroup()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;// 处理线程组</span>
    5. try {
    6. ServerBootstrap bootstrap = new ServerBootstrap()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    7. bootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.group</span>(bossGroup, workerGroup)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    8. bootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.channel</span>(NioServerSocketChannel<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.class</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    9. bootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.option</span>(ChannelOption<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.SO</span>_BACKLOG, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1024</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    10. bootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.childHandler</span>(new ChildChannelHandler())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    11. // 绑定端口,同步等待成功
    12. ChannelFuture future = bootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.bind</span>(port)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.sync</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    13. // 等待服务端监听端口关闭,等待服务端链路关闭之后main函数才退出
    14. future<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.channel</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.closeFuture</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.sync</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    15. } finally {
    16. // 优雅退出,释放线程池资源
    17. bossGroup<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.shutdownGracefully</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    18. workerGroup<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.shutdownGracefully</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    19. }
    20. }
    21. private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
    22. @Override
    23. protected void initChannel(SocketChannel ch) throws Exception {
    24. ch<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.pipeline</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addLast</span>(new TimeServerHandler())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    25. }
    26. }
    27. public static void main(String[] args) throws InterruptedException {
    28. int port = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8080</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    29. if (args != null && args<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.length</span> > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
    30. port = Integer<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.parseInt</span>(args[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>])<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    31. }
    32. new TimeServer()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.bind</span>(port)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    33. }

    }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

  • TimeClient

    package com.xpn.netty.netty;

    import io.netty.bootstrap.Bootstrap;
    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.NioSocketChannel;

    public class TimeClient {

    1. <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
    2. * @param args
    3. */</span>
    4. public static void main(String[] args) {
    5. // TODO Auto-generated method stub
    6. String host = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"localhost"</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    7. int port = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8080</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    8. EventLoopGroup workerGroup = new NioEventLoopGroup()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    9. try {
    10. Bootstrap bootstrap = new Bootstrap()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    11. bootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.group</span>(workerGroup)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    12. bootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.channel</span>(NioSocketChannel<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.class</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    13. bootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.option</span>(ChannelOption<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.SO</span>_KEEPALIVE, true)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    14. bootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.handler</span>(new ChannelInitializer<SocketChannel>() {
    15. @Override
    16. protected void initChannel(SocketChannel ch) throws Exception {
    17. ch<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.pipeline</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addLast</span>(new TimeClientHandler())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    18. }
    19. })<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    20. // 发起异步连接操作
    21. ChannelFuture future = bootstrap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.connect</span>(host, port)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.sync</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    22. future<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.channel</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.closeFuture</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.sync</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    23. } catch (Exception e) {
    24. workerGroup<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.shutdownGracefully</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    25. }
    26. }

    }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

  • TimeServerHandler

    package com.xpn.netty.netty;

    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.Unpooled;
    import io.netty.channel.ChannelHandlerAdapter;
    import io.netty.channel.ChannelHandlerContext;

    import java.util.Date;

    public class TimeServerHandler extends ChannelHandlerAdapter {

    1. <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    2. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">exceptionCaught</span>(ChannelHandlerContext ctx, Throwable cause)
    3. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Exception {
    4. <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// TODO Auto-generated method stub</span>
    5. cause.printStackTrace();
    6. ctx.close();
    7. }
    8. <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    9. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">channelRead</span>(ChannelHandlerContext ctx, Object msg)
    10. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Exception {
    11. ByteBuf buf = (ByteBuf) msg;
    12. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">byte</span>[] req = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">byte</span>[buf.readableBytes()];<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 获得缓冲区可读的字节数</span>
    13. buf.readBytes(req);
    14. String body = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> String(req, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"UTF-8"</span>);
    15. System.out.println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"the time server receive order : "</span> + body);
    16. String currentTime = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"query time order"</span>.equalsIgnoreCase(body) ? <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Date(
    17. System.currentTimeMillis()).toString() : <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"bad order"</span>;
    18. ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());
    19. ctx.write(resp);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 性能考虑,仅将待发送的消息发送到缓冲数组中,再通过调用flush方法,写入channel中</span>
    20. }
    21. <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    22. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">channelReadComplete</span>(ChannelHandlerContext ctx) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Exception {
    23. ctx.flush();<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 将消息发送队列中的消息写入到SocketChannel中发送给对方。</span>
    24. }

    }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

  • TimeClientHandler

    package com.xpn.netty.netty;

    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.Unpooled;
    import io.netty.channel.ChannelHandlerAdapter;
    import io.netty.channel.ChannelHandlerContext;

    import java.util.logging.Logger;

    public class TimeClientHandler extends ChannelHandlerAdapter {

    1. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Logger LOGGER = Logger
    2. .getLogger(TimeClientHandler.class.getName());
    3. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> ByteBuf firstMessage;
    4. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">TimeClientHandler</span>() {
    5. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">byte</span>[] req = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"query time order"</span>.getBytes();
    6. firstMessage = Unpooled.buffer(req.length);
    7. firstMessage.writeBytes(req);
    8. }
    9. <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    10. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">channelActive</span>(ChannelHandlerContext ctx) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Exception {
    11. ctx.writeAndFlush(firstMessage);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 将请求消息发送给服务端</span>
    12. }
    13. <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    14. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">exceptionCaught</span>(ChannelHandlerContext ctx, Throwable cause)
    15. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Exception {
    16. LOGGER.warning(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Unexpected exception from downstrema : "</span>
    17. + cause.getMessage());
    18. ctx.close();
    19. }
    20. <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    21. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">channelRead</span>(ChannelHandlerContext ctx, Object msg)
    22. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Exception {
    23. ByteBuf buf = (ByteBuf) msg;
    24. <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">byte</span>[] req = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">byte</span>[buf.readableBytes()];
    25. buf.readBytes(req);
    26. String body = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> String(req, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"UTF-8"</span>);
    27. System.out.println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Now is : "</span> + body);
    28. }

    }

发表评论

表情:
评论列表 (有 0 条评论,377人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Netty实现客户服务通信

    实现一个客户端与服务端通信的程序,可以使用socket网络编程来实现,而Netty作为一个封装了JDK的NIO通讯的异步事件驱动的网络应用框架,也同样可以实现。 1.创建M