這篇文章主要講解了“Netty中怎么實(shí)現(xiàn)前端發(fā)送消息,后端接收消息并返回”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Netty中怎么實(shí)現(xiàn)前端發(fā)送消息,后端接收消息并返回”吧!
網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、微信平臺(tái)小程序開(kāi)發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了資溪免費(fèi)建站歡迎大家使用!
今天通過(guò)一個(gè)故事來(lái)講解netty,主要講client和server端和下面的主要實(shí)現(xiàn)類。
客戶要去ktv唱歌,進(jìn)入ktv之前,門(mén)口會(huì)有招待服務(wù)生,然后招待服務(wù)生看到客戶之后,會(huì)安排你們給ktv內(nèi)部服務(wù)生給你們安排房間,然后帶你們進(jìn)入ktv房間唱歌,準(zhǔn)備開(kāi)始唱歌就要打開(kāi)音樂(lè),選好歌曲,打開(kāi)燈光等因素,之后這個(gè)期間你們可能會(huì)讓唱歌的服務(wù)生來(lái)助唱,讓會(huì)跳舞的服務(wù)生給你們跳舞,甚至讓服務(wù)生帶來(lái)酒或者吃的,直到你們唱歌結(jié)束付完錢(qián)離開(kāi)為止,整個(gè)過(guò)程就算結(jié)束。
專有名詞解釋:
client端:客戶
server端:ktv
mainGroup或者boosGroup:主線程組,相當(dāng)于ktv門(mén)口外的招待服務(wù)生
subGroup或者workerGroup:子線程組,相當(dāng)于ktv內(nèi)部服務(wù)生,負(fù)責(zé)安排房間的,由招待服務(wù)生通知內(nèi)部服務(wù)生安排給他們的
ServerBootstrap :客戶進(jìn)入ktv之前到離開(kāi)ktv之后的整個(gè)流程
HelloServerInitializer:進(jìn)入ktv房間之后的整個(gè)流程
CustomHandler :分別代表唱歌服務(wù)生、端茶送水服務(wù)生、跳舞服務(wù)生各個(gè)實(shí)現(xiàn)的功能等等
import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; /** * @Description: 實(shí)現(xiàn)客戶端發(fā)送一個(gè)請(qǐng)求,服務(wù)器會(huì)返回 hello netty */ public class HelloServer { public static void main(String[] args) throws Exception { // 定義一對(duì)線程組 // 主線程組, 用于接受客戶端的連接,但是不做任何處理,跟老板一樣,不做事 EventLoopGroup bossGroup = new NioEventLoopGroup(); // 從線程組, 老板線程組會(huì)把任務(wù)丟給他,讓手下線程組去做任務(wù) EventLoopGroup workerGroup = new NioEventLoopGroup(); try { // netty服務(wù)器的創(chuàng)建, ServerBootstrap 是一個(gè)啟動(dòng)類 ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) // 設(shè)置主從線程組 .channel(NioServerSocketChannel.class) // 設(shè)置nio的雙向通道 .childHandler(new HelloServerInitializer()); // 子處理器,用于處理workerGroup // 啟動(dòng)server,并且設(shè)置8088為啟動(dòng)的端口號(hào),同時(shí)啟動(dòng)方式為同步 ChannelFuture channelFuture = serverBootstrap.bind(8088).sync(); // 監(jiān)聽(tīng)關(guān)閉的channel,設(shè)置位同步方式 channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpServerCodec; /** * @Description: 初始化器,channel注冊(cè)后,會(huì)執(zhí)行里面的相應(yīng)的初始化方法 */ public class HelloServerInitializer extends ChannelInitializer{ @Override protected void initChannel(SocketChannel channel) throws Exception { // 通過(guò)SocketChannel去獲得對(duì)應(yīng)的管道 ChannelPipeline pipeline = channel.pipeline(); // 通過(guò)管道,添加handler // HttpServerCodec是由netty自己提供的助手類,可以理解為攔截器 // 當(dāng)請(qǐng)求到服務(wù)端,我們需要做解碼,響應(yīng)到客戶端做編碼 pipeline.addLast("HttpServerCodec", new HttpServerCodec()); // 添加自定義的助手類,返回 "hello netty~" pipeline.addLast("customHandler", new CustomHandler()); } }
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.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpObject; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.util.CharsetUtil; /** * @Description: 創(chuàng)建自定義助手類 */ // SimpleChannelInboundHandler: 對(duì)于請(qǐng)求來(lái)講,其實(shí)相當(dāng)于[入站,入境] public class CustomHandler extends SimpleChannelInboundHandler{ @Override protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { // 獲取channel Channel channel = ctx.channel(); if (msg instanceof HttpRequest) { // 顯示客戶端的遠(yuǎn)程地址 System.out.println(channel.remoteAddress()); // 定義發(fā)送的數(shù)據(jù)消息 ByteBuf content = Unpooled.copiedBuffer("Hello netty~", CharsetUtil.UTF_8); // 構(gòu)建一個(gè)http response FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content); // 為響應(yīng)增加數(shù)據(jù)類型和長(zhǎng)度 response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain"); response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes()); // 把響應(yīng)刷到客戶端 ctx.writeAndFlush(response); } } @Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { System.out.println("channel。。。注冊(cè)"); super.channelRegistered(ctx); } @Override public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { System.out.println("channel。。。移除"); super.channelUnregistered(ctx); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("channel。。。活躍"); super.channelActive(ctx); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("channel。。。不活躍"); super.channelInactive(ctx); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { System.out.println("channeld讀取完畢。。。"); super.channelReadComplete(ctx); } @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { System.out.println("用戶事件觸發(fā)。。。"); super.userEventTriggered(ctx, evt); } @Override public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { System.out.println("channel可寫(xiě)更改"); super.channelWritabilityChanged(ctx); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { System.out.println("補(bǔ)貨到異常"); super.exceptionCaught(ctx, cause); } @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { System.out.println("助手類添加"); super.handlerAdded(ctx); } @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { System.out.println("助手類移除"); super.handlerRemoved(ctx); } }
io.netty netty-all 4.1.25.Final
打開(kāi)瀏覽器:localhost:8088,出現(xiàn)下面錯(cuò)誤情況,如果用postman工具的話,就會(huì)發(fā)現(xiàn)不報(bào)錯(cuò),因?yàn)闉g覽器會(huì)自動(dòng)關(guān)閉。
解決方案:將super.exceptionCauht(ctx,case);注釋掉就好了
@Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { //super.exceptionCaught(ctx, cause); }
感謝各位的閱讀,以上就是“Netty中怎么實(shí)現(xiàn)前端發(fā)送消息,后端接收消息并返回”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Netty中怎么實(shí)現(xiàn)前端發(fā)送消息,后端接收消息并返回這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!