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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM