Netty 简单服务器 (三)
生活随笔
收集整理的這篇文章主要介紹了
Netty 简单服务器 (三)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
2019獨角獸企業重金招聘Python工程師標準>>>
經過對Netty的基礎認識,設計模型的初步了解,來寫個測試,試試手感
上篇也說到官方推薦我們使用主從線程池模型,那就選擇這個模型進行操作
?
需要操作的步驟:
- 需要構建兩個主從線程組
- 寫一個服務器入口啟動器
- 設置Channel雙向通道
- 配置線程池處理器,操作Channel
- 監聽機制,比如監聽啟動端口,監聽服務器關閉等等
?
利用IDEA快速一鍵構建一個springboot項目,然后去maven倉庫找netty依賴,找個4.x.x最新的依賴就可以,5.x.x的版本已經被廢棄,不要使用
<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.32.Final</version> </dependency>?
簡單的目錄展示
?
為了簡單直接測試,在啟動類同級建一個NettyServer啟動類,一個main方法就可以了,貼圖:
package com.yus.netty;import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel;/*** Netty 啟動類* 簡單實現客戶端發送連接請求,服務器返回信息*/ public class NettyServer {public static void main(String[] args) throws InterruptedException {// 1。定義兩個主從線程組// 主線程組 --- 用于接收客戶端的連接,不處理事件,就是接任務的包工頭EventLoopGroup primaryGroup = new NioEventLoopGroup();// 從線程組 --- 處理主線程組接收連接注冊之后的事件,就是純打工的EventLoopGroup subGroup = new NioEventLoopGroup();try {// 2。服務啟動器ServerBootstrap bootstrap = new ServerBootstrap();// 根據Netty選擇不同的線程模型,選擇不同的重載方法,這里是主從線程模型// 業務的分配等功能,都由bootstrap負責處理,不需要我們處理// .channel --- 設置通道類型// .childHandler 針對[subGroup從線程組]處理每一個channel,可以選擇實現類,也可以自定義內部類的方式構建// 每一個Channel由多個handle共同組成管道(pipeline)bootstrap.group(primaryGroup, subGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInit());// 3。綁定啟動端口,確保鏈接啟動,使用sync同步等待端口啟動完成ChannelFuture future = bootstrap.bind(8088).sync();// 4。用于監聽關閉的Channel ,同步方式future.channel().closeFuture().sync();} finally {//使用shutdownGracefully關閉 ,原shutdown方法已經過時primaryGroup.shutdownGracefully();subGroup.shutdownGracefully();}} }?
初始化器
package com.yus.netty;import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpServerCodec;/*** 初始化器 --- 初始化每一個Channel* .channel設置的類型是泛型*/ public class ChannelInit extends ChannelInitializer<SocketChannel> {/*** channel pipeline handle 三者的關系** 1。注冊的channel通道* 2。進入初始化器pipeline管道* 3。pipeline包含多個handle,共同處理channel,也可以理解為攔截處理*/@Overrideprotected void initChannel(SocketChannel channel) throws Exception {//通過 channel 獲取管道ChannelPipeline pipeline = channel.pipeline();//通過管道 添加handle ,name選填//使用netty提供的一個編解碼HttpServerCodec//HttpServerCodec:當請求到服務端,需要解碼,然后響應客戶端,需要編碼pipeline.addLast("HttpServerCodec",new HttpServerCodec());//添加自定義的助手類pipeline.addLast("HelloHandle",new HelloHandle());} }?
助手類
package com.yus.netty;import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.*; import io.netty.util.CharsetUtil;/*** 自定義的助手類* <p>* 客戶端向服務端發起請求之后,數據存放在緩沖區* 然后服務端從緩沖區中讀取,整體操作是一個入棧* <p>* SimpleChannelInboundHandler 入棧* 要往客戶端寫點東西返回,使用HttpObject*/ public class HelloHandle extends SimpleChannelInboundHandler<HttpObject> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {Channel channel = ctx.channel();System.out.println("遠程地址:" + channel.remoteAddress());//操作 緩沖區 參數(返回自定義字符串,字符集) 此處設置的字符集僅供ByteBuf使用ByteBuf buf = Unpooled.copiedBuffer("Hello,Netty,會亂碼嗎?!", CharsetUtil.UTF_8);//構建響應,將buf數據返回 參數(http版本號,http返回狀態,)FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, buf);//設置響應頭部的數據類型以及長度,返回需要設置charset=UTF-8,針對response設置response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain;charset=UTF-8");response.headers().set(HttpHeaderNames.CONTENT_LENGTH,buf.readableBytes());//把response響應到客戶端//write只將response寫到緩沖區,writeAndFlush將response寫到緩沖區,并刷到客戶端ctx.writeAndFlush(response);} }?
啟動訪問: localhost:8088?
-----------------------------------------------------------
轉載于:https://my.oschina.net/u/3829444/blog/2990127
總結
以上是生活随笔為你收集整理的Netty 简单服务器 (三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 写给自己的2019年规划
- 下一篇: docker: docker安装和镜像下