netty实现TCP长连接

所用jar包

netty-all-4.1.30.Final.jar 密码:rzwe

NettyConfig.java,存放连接的客户端

 1 import io.netty.channel.group.ChannelGroup;
 2 import io.netty.channel.group.DefaultChannelGroup;
 3 import io.netty.util.concurrent.GlobalEventExecutor;
 4 
 5 public class NettyConfig {
 6     
 7     /**
 8      * 存储每一个客户端接入进来时的channel对象
 9      */
10     public static ChannelGroup group = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
11     
12 }

 

Server.java,netty配置信息

 1 import io.netty.bootstrap.ServerBootstrap;
 2 import io.netty.channel.ChannelFuture;
 3 import io.netty.channel.ChannelInitializer;
 4 import io.netty.channel.ChannelOption;
 5 import io.netty.channel.ChannelPipeline;
 6 import io.netty.channel.EventLoopGroup;
 7 import io.netty.channel.nio.NioEventLoopGroup;
 8 import io.netty.channel.socket.ServerSocketChannel;
 9 import io.netty.channel.socket.SocketChannel;
10 import io.netty.channel.socket.nio.NioServerSocketChannel;
11 
12 public class Server {
13     private int port;
14     private ServerSocketChannel serverSocketChannel;
15  
16     public Server(int port){
17         this.port = port;
18         bind();
19     }
20     
21     private void bind() {
22         Thread thread = new Thread(new Runnable() {
23             @Override
24             public void run() {
25                 //服务端要建立两个group,一个负责接收客户端的连接,一个负责处理数据传输
26                 //连接处理group
27                 EventLoopGroup boss = new NioEventLoopGroup();
28                 //事件处理group
29                 EventLoopGroup worker = new NioEventLoopGroup();
30                 ServerBootstrap bootstrap = new ServerBootstrap();
31                 // 绑定处理group
32                 bootstrap.group(boss, worker).channel(NioServerSocketChannel.class)
33                         //保持连接数
34                         .option(ChannelOption.SO_BACKLOG, 300)
35                         //有数据立即发送
36                         .option(ChannelOption.TCP_NODELAY, true)
37                         //保持连接
38                         .childOption(ChannelOption.SO_KEEPALIVE, true)
39                         //处理新连接
40                         .childHandler(new ChannelInitializer<SocketChannel>() {
41                             @Override
42                             protected void initChannel(SocketChannel sc) throws Exception {
43                                 // 增加任务处理
44                                 ChannelPipeline p = sc.pipeline();
45                                 p.addLast(
46 //                                        //使用了netty自带的编码器和解码器
47 //                                        new StringDecoder(),
48 //                                        new StringEncoder(),
49                                         //心跳检测,读超时,写超时,读写超时
50                                         //new IdleStateHandler(5, 0, 0, TimeUnit.SECONDS),
51                                         //自定义的处理器
52                                         new ServerHandler());
53                             }
54                         });
55  
56                 //绑定端口,同步等待成功
57                 ChannelFuture future;
58                 try {
59                     future = bootstrap.bind(port).sync();
60                     if (future.isSuccess()) {
61                         serverSocketChannel = (ServerSocketChannel) future.channel();
62                         System.out.println("服务端启动成功,端口:"+port);
63                     } else {
64                         System.out.println("服务端启动失败!");
65                     }
66                     
67                     //等待服务监听端口关闭,就是由于这里会将线程阻塞,导致无法发送信息,所以我这里开了线程
68                     future.channel().closeFuture().sync();
69                 } catch (Exception e) {
70                     e.printStackTrace();
71                 }
72                 finally {
73                     //优雅地退出,释放线程池资源
74                     boss.shutdownGracefully();
75                     worker.shutdownGracefully();
76                 }
77             }
78         });
79         thread.start();
80     }
81     
82     public void sendMessage(Object msg){
83         if(serverSocketChannel != null){
84             serverSocketChannel.writeAndFlush(msg);
85         }
86     }
87     
88     public static void main(String[] args) {
89         Server server = new Server(8088);
90     }
91 }

 

ServerHandler.java,业务处理

 1 import io.netty.channel.ChannelHandlerContext;
 2 import io.netty.channel.ChannelInboundHandlerAdapter;
 3 
 4 public class ServerHandler extends ChannelInboundHandlerAdapter {    
 5       
 6     /**
 7      * 客户端与服务端创建连接的时候调用
 8      */
 9     @Override
10     public void channelActive(ChannelHandlerContext ctx) throws Exception {
11         System.out.println("客户端与服务端连接开始...");
12         NettyConfig.group.add(ctx.channel());
13     }
14  
15     /**
16      * 客户端与服务端断开连接时调用
17      */
18     @Override
19     public void channelInactive(ChannelHandlerContext ctx) throws Exception {
20         System.out.println("客户端与服务端连接关闭...");
21         NettyConfig.group.remove(ctx.channel());
22     }
23  
24     /**
25      * 服务端接收客户端发送过来的数据结束之后调用
26      */
27     @Override
28     public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
29         ctx.flush();
30         System.out.println("信息接收完毕...");
31     }
32  
33     /**
34      * 工程出现异常的时候调用
35      */
36     @Override
37     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
38         cause.printStackTrace();
39         ctx.close();
40     }
41  
42     /**
43      * 服务端处理客户端websocket请求的核心方法,这里接收了客户端发来的信息
44      */
45     @Override
46     public void channelRead(ChannelHandlerContext channelHandlerContext, Object info) throws Exception {
47         System.out.println("接收到了:"+info);
48 ByteBuf buf = (ByteBuf) info;
49 byte[] req = new byte[buf.readableBytes()];
50 buf.readBytes(req);
51 String body = new String(req, "UTF-8");
52 System.out.println("接收客户端数据:" + body);
53 ByteBuf pingMessage = Unpooled.buffer();
54 pingMessage.writeBytes(req);
55 channelHandlerContext.writeAndFlush(pingMessage);
56 
57         
58         //服务端使用这个就能向 每个连接上来的客户端群发消息
59         //NettyConfig.group.writeAndFlush(info);
60 //        Iterator<Channel> iterator = NettyConfig.group.iterator();
61 //        while(iterator.hasNext()){
62 //            //打印出所有客户端的远程地址
63 //            System.out.println((iterator.next()).remoteAddress());
64 //        }
65     }
66     
67     
68 }

 

使用网络调试助手进行连接测试 下载地址

https://www.wanpishe.top/detail?blogId=fc62fce2-020a-4815-8388-0903e4a54e1f

 

posted @ 2018-12-14 16:08  粉红顽皮蛇  阅读(18937)  评论(1编辑  收藏  举报