Netty入门(一)-- 客户端示例

前言

  本文主要实现基于Netty实现客户端,向服务器定时发送数据

如下为一个简单的Netty实例,本实例主要描述了Client向服务端定时发送数据,并实现重连机制及轮询发送数据

先直接上代码,后续在整理一些用法相关知识

例子中如有误,欢迎各位指正

1、pom.xml

1         <dependency>
2             <groupId>io.netty</groupId>
3             <artifactId>netty-all</artifactId>
4             <version>4.1.36.Final</version>
5         </dependency>

  2、NettyClient.java:主要为初始化Client Socket

 1 import io.netty.bootstrap.Bootstrap;
 2 import io.netty.channel.*;
 3 import io.netty.channel.nio.NioEventLoopGroup;
 4 import io.netty.channel.socket.nio.NioSocketChannel;
 5 import io.netty.handler.codec.string.StringDecoder;
 6 import io.netty.handler.codec.string.StringEncoder;
 7 import io.netty.util.CharsetUtil;
 8 
 9 
10 public class NettyClientTest implements Runnable{
11 
12     private static volatile EventLoopGroup workerGroup;
13 
14     private String ip;
15 
16     private int port;
17 
18     public NettyClientTest(String ip, int port) {
19         this.ip = ip;
20         this.port = port;
21     }
22 
23     @Override
24     public void run() {
25         // 客户端的配置
26         workerGroup= new NioEventLoopGroup();
27         try {
28             Bootstrap bootstrap = new Bootstrap();
29             bootstrap.group(workerGroup)
30                     .channel(NioSocketChannel.class)
31                     .option(ChannelOption.TCP_NODELAY, true)
32                     .handler(new ChannelInitializer() {
33                         @Override
34                         protected void initChannel(Channel channel) throws Exception {
35                             ChannelPipeline p = channel.pipeline();
36                             //编码格式
37                             p.addLast("decoder", new StringDecoder(CharsetUtil.UTF_8))
38                                     .addLast("encoder", new StringEncoder(CharsetUtil.UTF_8))
39                                     //具体的客户端实现操作类
40                                     .addLast(new NettyClientHandlerTest(bootstrap, ip, port));
41                         }
42                     });
43 
44             ChannelFuture future = null;
45             /**
46              *防止初次链接不上 每隔十秒重连一次
47              */
48             while (future == null || !future.isSuccess()) {
49                 try {
50                     future = bootstrap.connect(ip, port).sync();
51                 } catch (Exception ex) {
52                     System.out.println("重连中。。。。");
53                     Thread.sleep(10000);
54                 }
55             }
56 
57 
58             future.channel().closeFuture().sync();
59         } catch (InterruptedException e) {
60             e.printStackTrace();
61         } finally {
62             //workerGroup.shutdownGracefully();
63         }
64     }
65 
66 
67 
68     public static void main(String[] args) {
69 
70         //开启单条条线程,每条线程就相当于一个客户端
71         new NettyClientTest("localhost",10002).run();
72     }
73 }

    3、NettyClientHandlerTest.java:配合NettyClient,完成消息的读取操作以及业务处理。

  

  1 import io.netty.bootstrap.Bootstrap;
  2 import io.netty.channel.*;
  3 import java.net.InetSocketAddress;
  4 import java.util.concurrent.TimeUnit;
  5 
  6 
  7 
  8 public class NettyClientHandlerTest extends ChannelInboundHandlerAdapter{
  9 
 10     /**
 11      *
 12      */
 13     private final Bootstrap bootstrap;
 14 
 15     /**
 16      * 交互channel
 17      */
 18     private static Channel channel;
 19 
 20     /**
 21      * 服务端ip  重连时使用
 22      */
 23     private String ip;
 24 
 25     /**
 26      * 服务端端口
 27      */
 28     private int port;
 29 
 30 
 31     /**
 32      * 断线重连等待时间 /S
 33      */
 34     private final static int reconnectDelay = 10;
 35 
 36     public NettyClientHandlerTest(Bootstrap bootstrap, String ip, int port) {
 37         this.bootstrap = bootstrap;
 38         this.ip = ip;
 39         this.port = port;
 40     }
 41 
 42     /**
 43      * 客户端连接服务器后被调用
 44      * @param ctx
 45      */
 46     @Override
 47     public void channelActive(ChannelHandlerContext ctx) {
 48         channel = ctx.channel();
 49         ctx.fireChannelActive();
 50         channelWrite();
 51     }
 52 
 53     /**
 54      * @param ctx
 55      * @DESCRIPTION: 服务端端终止连接 后触发此函数
 56      * @return: void
 57      */
 58     @Override
 59     public void channelInactive(ChannelHandlerContext ctx) {
 60 
 61         ctx.fireChannelInactive();
 62         System.out.println("服务端终止了服务");
 63         try {
 64             super.channelInactive(ctx);
 65         } catch (Exception e) {
 66             e.printStackTrace();
 67         }
 68         //断开连接后实现重连机制
 69         ctx.channel().eventLoop().schedule(() -> doConnect(), reconnectDelay, TimeUnit.SECONDS);
 70     }
 71 
 72     /**
 73      * 每隔十秒重连一次
 74      */
 75     private void doConnect() {
 76         ChannelFuture future = bootstrap.connect(new InetSocketAddress(ip, port));
 77         future.addListener(new ChannelFutureListener() {
 78             public void operationComplete(ChannelFuture f) throws Exception {
 79                 if (f.isSuccess()) {
 80                     System.out.println("Started Tcp Client: ");
 81                 } else {
 82                     System.out.println("Started Tcp Client Failed: ");
 83                     f.channel().eventLoop().schedule(() -> doConnect(), reconnectDelay, TimeUnit.SECONDS);
 84                 }
 85             }
 86         });
 87     }
 88 
 89     /**
 90      * 从服务器接收到数据后调用
 91      * @param ctx
 92      * @param msg
 93      */
 94     @Override
 95     public void channelRead(ChannelHandlerContext ctx, Object msg) {
 96 
 97         System.out.println("回写数据:" + msg);
 98     }
 99 
100 
101     /**
102      * 发生异常时被调用
103      * @param ctx
104      * @param cause
105      */
106     @Override
107     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
108 
109         //cause.printStackTrace();
110         System.out.println("服务端发生异常【" + cause.getMessage() + "");
111         ctx.close();
112     }
113 
114     /**
115      * 新启一个线程  轮询发送数据
116      * @DESCRIPTION: 客户端给服务端发送消息
117      * @return: void
118      */
119     public void channelWrite() {
120         new Thread(new DataSendTest(channel)).start();
121     }
122 }

   4、DataSendTest.java:数据发送处理

  

 1 import io.netty.buffer.ByteBuf;
 2 import io.netty.buffer.Unpooled;
 3 import io.netty.channel.Channel;
 4 
 5 
 6 public class DataSendTest implements Runnable{
 7 
 8     /**
 9      * 与服务端交互的通道
10      */
11     private Channel channel;
12 
13     public DataSendTest(Channel channel){
14         this.channel = channel;
15     }
16 
17     /**
18      * 轮询发送数据
19      */
20     @Override
21     public void run() {
22         while (true) {
23             try{
24                 //channel通道关闭时  不发送数据
25                 if (!channel.isActive()) {
26                     break;
27                 }
28                 byte[] bytes = new byte[]{10,12,13};
29                 ByteBuf byteBuf = Unpooled.wrappedBuffer(bytes);
30 
31                 channel.write(byteBuf);
32                 channel.flush();
33 
34                 Thread.sleep(1000);
35             } catch (Exception ex) {
36 
37             }
38         }
39     }
40 }

 

posted @ 2019-12-09 21:26  遗失的岁月  阅读(814)  评论(0编辑  收藏  举报