欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Netty網(wǎng)絡(luò)編程實(shí)戰(zhàn)之搭建Netty服務(wù)器

 更新時(shí)間:2022年10月10日 10:17:06   作者:哪?吒  
Netty是JBOSS開(kāi)源的一款NIO網(wǎng)絡(luò)編程框架,可用于快速開(kāi)發(fā)網(wǎng)絡(luò)的應(yīng)用。Netty是一個(gè)異步的、基于事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用框架,用于快速開(kāi)發(fā)高性能的服務(wù)端和客戶(hù)端。本文將詳細(xì)說(shuō)說(shuō)如何搭建Netty服務(wù)器,需要的可以參考一下

一、Netty是什么

Netty是JBOSS開(kāi)源的一款NIO網(wǎng)絡(luò)編程框架,可用于快速開(kāi)發(fā)網(wǎng)絡(luò)的應(yīng)用。Netty是一個(gè)異步的、基于事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用框架,用于快速開(kāi)發(fā)高性能的服務(wù)端和客戶(hù)端??梢詷O大的簡(jiǎn)化基于TCP、UDP等協(xié)議的網(wǎng)絡(luò)服務(wù)。并且Netty對(duì)于各種傳輸類(lèi)型(阻塞或非阻塞式的socket)、通信方式(HTTP或websocket)都提供了統(tǒng)一的API接口,提供了靈活的可擴(kuò)展性,高度可自定義的線程模型(多線程、線程池等),支持使用無(wú)連接的數(shù)據(jù)報(bào)UDP進(jìn)行通信,具有高吞吐量、低延遲、資源消耗低、最低限度的內(nèi)存復(fù)制等特性。除了優(yōu)越的性能外,Netty還支持SSL/TLS和StartTLS等加密傳輸協(xié)議,保證了數(shù)據(jù)傳輸?shù)陌踩浴?/p>

在實(shí)際使用時(shí),Netty可以作為Socket編程的中間件;也可以和Protobuf技術(shù)結(jié)合使用,實(shí)現(xiàn)一個(gè)RPC框架,實(shí)現(xiàn)遠(yuǎn)程過(guò)程調(diào)用;也可以作為一個(gè)websocket的長(zhǎng)鏈接服務(wù)器,實(shí)現(xiàn)客戶(hù)端和服務(wù)端的長(zhǎng)連接通信。

二、Hello Netty

使用Netty作為一個(gè)Web服務(wù)器,用于接收用戶(hù)請(qǐng)求并給出響應(yīng)。

Netty程序一般都是按套路來(lái)寫(xiě),依次編寫(xiě)主程序類(lèi)、自定義初始化器、自定義處理器。

1、主程序類(lèi)MyNettyServerTest

通過(guò)ServerBootstrap注冊(cè)serverGroup和clientGroup兩個(gè)事件循環(huán)組,其中serverGroup用于獲取客戶(hù)端連接,clientGroup用于處理客戶(hù)端連接,類(lèi)似于常見(jiàn)的Master-Slave結(jié)構(gòu)。

2、初始化器MyNettyServerInitializer

繼承Netty提供的初始化器ChannelInitializer。

Netty封裝了各種各樣的內(nèi)置處理器,用于實(shí)現(xiàn)各種功能。并且ChannelInitializer的initChannel()方法會(huì)在某一個(gè)連接注冊(cè)到Channel后立即被觸發(fā)調(diào)用。因此,可以根據(jù)業(yè)務(wù)需求,在initChannel()中添加若干個(gè)Netty內(nèi)置處理器,利用Netty強(qiáng)大的類(lèi)庫(kù)直接處理大部分業(yè)務(wù)。最后再在initChannel()中添加一個(gè)自定義處理器,用于實(shí)現(xiàn)特定業(yè)務(wù)的具體功能。

3、自定義處理器MyNettyServerHandler

繼承SimpleChannelInboundHandler,該父類(lèi)的channelRead0()方法可以接收客戶(hù)端的所有請(qǐng)求,并作出響應(yīng),輸出“Hello Netty”。

簡(jiǎn)單講,Netty程序就是通過(guò)主程序類(lèi)關(guān)聯(lián)自定義初始化器,然后在初始化器中加入Netty內(nèi)置處理器和自定義處理器,最后在自定義處理器中編寫(xiě)處理特定需求的業(yè)務(wù)代碼。

三、代碼實(shí)例

1、maven中加入netty-all

<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.68.Final</version>
</dependency>

2、主程序類(lèi)MyNettyServerTest

package com.guor.demo.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;

/**
 * 主程序類(lèi)
 */
public class MyNettyServerTest {
    public static void main(String[] args) throws InterruptedException {
        /**
         * EventLoopGroup:事件循環(huán)組,是一個(gè)線程池,也是一個(gè)死循環(huán),用于不斷地接收用戶(hù)請(qǐng)求;
         * serverGroup:用戶(hù)監(jiān)聽(tīng)及建立連接,并把每一個(gè)連接抽象為一個(gè)channel,最后再將連接交給clientGroup處理;
         * clientGroup:真正的處理連接
         */
        EventLoopGroup serverGroup = new NioEventLoopGroup();
        EventLoopGroup clientGroup = new NioEventLoopGroup();
        try {
            // 服務(wù)端啟動(dòng)時(shí)的初始化操作
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            // 1、將serverGroup和clientGroup注冊(cè)到服務(wù)端的Channel上;
            // 2、注冊(cè)一個(gè)服務(wù)端的初始化器MyNettyServerInitializer;
            // 3、該初始化器中的initChannel()方法會(huì)在連接被注冊(cè)到Channel后立刻執(zhí)行;
            // 5、最后將端口號(hào)綁定到8080;
            ChannelFuture channelFuture = serverBootstrap.group(serverGroup, clientGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new MyNettyServerInitializer()).bind(8080).sync();
            channelFuture.channel().closeFuture().sync();
        }catch (Exception e){
            System.out.println(e);
        }finally {
            serverGroup.shutdownGracefully();
            clientGroup.shutdownGracefully();
        }
    }
}

3、初始化器MyNettyServerInitializer

package com.guor.demo.netty;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;

/**
 * 初始化器
 */
public class MyNettyServerInitializer extends ChannelInitializer<SocketChannel> {

    // 連接被注冊(cè)到Channel后,立刻執(zhí)行此方法
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        // 加入netty提供的處理器
        pipeline.addLast("HttpServerCodec",new HttpServerCodec());
        // 增加自定義處理器MyNettyServerHandler,用于實(shí)際處理請(qǐng)求,并給出響應(yīng)
        pipeline.addLast("MyNettyServerHandler",new MyNettyServerHandler());
    }
}

4、自定義處理器MyNettyServerHandler

package com.guor.demo.netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

/**
 * 自定義處理器
 * Inbound代表"進(jìn)入"的請(qǐng)求
 */
public class MyNettyServerHandler extends SimpleChannelInboundHandler<HttpObject> {

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, HttpObject httpObject) throws Exception {
        // 定義響應(yīng)的內(nèi)容
        ByteBuf byteBuf = Unpooled.copiedBuffer("Hello Netty", CharsetUtil.UTF_8);
        DefaultFullHttpResponse defaultFullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, byteBuf);
        defaultFullHttpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
        byteBuf.readableBytes();
        // 等響應(yīng)返回給客戶(hù)端
        channelHandlerContext.writeAndFlush(defaultFullHttpResponse);
    }
}

5、通過(guò)curl http://localhost:8080訪問(wèn)Netty服務(wù)

此時(shí),可能會(huì)提示curl不是內(nèi)部或外部命令,如何解決?

四、curl不是內(nèi)部或外部命令

1、下載curl for 64-bit

https://curl.se/windows/

2、將zip解壓到文件夾

3、在環(huán)境變量中配置

五、重寫(xiě)SimpleChannelInboundHandler中一些重要的回調(diào)方法

1、重寫(xiě)回調(diào)方法

package com.guor.demo.netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

/**
 * 自定義處理器
 * Inbound代表"進(jìn)入"的請(qǐng)求
 */
public class MyNettyServerHandler extends SimpleChannelInboundHandler<HttpObject> {

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, HttpObject httpObject) throws Exception {
        // 定義響應(yīng)的內(nèi)容
        ByteBuf byteBuf = Unpooled.copiedBuffer("Hello Netty", CharsetUtil.UTF_8);
        DefaultFullHttpResponse defaultFullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, byteBuf);
        defaultFullHttpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
        byteBuf.readableBytes();
        // 等響應(yīng)返回給客戶(hù)端
        channelHandlerContext.writeAndFlush(defaultFullHttpResponse);
    }

    /**
     * 增加新處理器時(shí),觸發(fā)此方法
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception{
        System.out.println("1、handlerAdded、增加了新的處理器");
        super.handlerAdded(ctx);
    }

    /**
     * 當(dāng)通道被注冊(cè)到一個(gè)事件循環(huán)組EventLoop上時(shí),觸發(fā)此方法
     */
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception{
        System.out.println("2、channelRegistered、通道被注冊(cè)");
        super.channelRegistered(ctx);
    }

    /**
     * 當(dāng)遠(yuǎn)端處于活躍狀態(tài)時(shí)(連接到了某個(gè)遠(yuǎn)端,可以收發(fā)數(shù)據(jù)),執(zhí)行此方法
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception{
        System.out.println("3、channelActive、通道連接到了遠(yuǎn)端,處于活躍狀態(tài)");
        super.channelActive(ctx);
    }

    /**
     * 當(dāng)通道處于非活躍狀態(tài)時(shí)(與遠(yuǎn)端斷開(kāi)了連接),執(zhí)行此方法
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception{
        System.out.println("4、channelInactive、通道遠(yuǎn)端斷開(kāi)了連接,處于非活躍狀態(tài)");
        super.channelInactive(ctx);
    }

    /**
     * 當(dāng)通道被取消了注冊(cè)時(shí),執(zhí)行此方法
     */
    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception{
        System.out.println("5、channelUnregistered、通道被取消了注冊(cè)");
        super.channelUnregistered(ctx);
    }

    /**
     * 當(dāng)程序發(fā)生異常,執(zhí)行此方法
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,Throwable e) throws Exception{
        System.out.println("6、exceptionCaught、程序發(fā)生了異常");
        e.printStackTrace();
        ctx.close();
    }
}

2、通過(guò)curl http://localhost:8080訪問(wèn)Netty服務(wù)

3、控制臺(tái)輸出

4、ctrl + c停止訪問(wèn)

以上就是Netty網(wǎng)絡(luò)編程實(shí)戰(zhàn)之搭建Netty服務(wù)器的詳細(xì)內(nèi)容,更多關(guān)于搭建Netty服務(wù)器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論