Netty簡(jiǎn)單入門

軟件要求

  • 最新版本Netty
  • JDK1.6以上

寫一個(gè)Discard Server

在這個(gè)世界上最簡(jiǎn)單的協(xié)議不是 Hello world祝闻,而是DISCARD。該協(xié)議將一切接收到的數(shù)據(jù)全部舍棄涣觉,不做任何響應(yīng)。因此展箱,實(shí)現(xiàn)DISCARD協(xié)議旨枯,你唯一需要做的事情是忽略所有接收到的數(shù)據(jù)

  • 接下來(lái)混驰,我們直接從handler的實(shí)現(xiàn)開始編寫Discard服務(wù)攀隔,handler主要用于處理Netty產(chǎn)生的IO事件皂贩。
package discard.server;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * @ClassName DiscardHandler
 * @Description TODO
 * @Author xiuc_shi
 * @Date 2020/8/29 下午 1:17
 * @Version 1.0
 **/
public class DiscardHandler extends ChannelInboundHandlerAdapter {//(1)

    @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {//(2)
        //舍棄接收到的消息
        //        ((ByteBuf)msg).release();//(3)

        ByteBuf in = (ByteBuf)msg;
        while (in.isReadable()) {
            System.out.println((char)in.readByte());
            System.out.flush();
        }
    }

    @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {//(4)
        super.exceptionCaught(ctx, cause);
    }
}

為了看到服務(wù)器是否真的接收到數(shù)據(jù),我們直接將數(shù)據(jù)打印出來(lái)昆汹。

  1. DiscardServerHandler繼承了ChannelInboundHandlerAdapter明刷,該類是ChannelInboundHandler的一個(gè)實(shí)現(xiàn)。ChannelInboundHandler提供了很多事件處理方法供你重寫满粗。
  2. 我們此處重寫了channelRead()事件處理方法辈末。當(dāng)有新消息從客戶端發(fā)出,該方法被調(diào)用來(lái)接收來(lái)自客戶端的消息映皆。在這個(gè)例子中挤聘,接收消息的類型是ByteBuf
  3. 對(duì)于DISCARD協(xié)議的實(shí)現(xiàn)捅彻,處理器會(huì)忽略接收到的消息组去。ByteBuf是一個(gè)引用計(jì)數(shù)對(duì)象(Reference-counted Object),因此必須通過(guò)調(diào)用release()方法顯式釋放步淹。通常从隆,channelRead()事件處理方法如下實(shí)現(xiàn):
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
    try {
        // Do something with msg
    } finally {
        ReferenceCountUtil.release(msg);
    }
}
  1. 當(dāng)處理器在處理事件是發(fā)生異常或者出現(xiàn)IO錯(cuò)誤時(shí)缭裆,exceptionCaught()事件處理方法會(huì)觸發(fā)拋出Throwable键闺。大多數(shù)情況下,應(yīng)當(dāng)記錄日志并且關(guān)閉相關(guān)的channel澈驼。實(shí)現(xiàn)不盡相同辛燥,根據(jù)你的需求,例如有時(shí)還希望在關(guān)閉連接之前發(fā)送錯(cuò)誤碼響應(yīng)消息盅藻。
  • 至此购桑,我們已經(jīng)實(shí)現(xiàn)了DISCARD服務(wù)器的第一步畅铭。接下來(lái)氏淑,寫main方法用來(lái)啟動(dòng)DiscardServerHandler服務(wù)。
package discard.server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * @ClassName Server
 * @Description TODO
 * @Author xiuc_shi
 * @Date 2020/8/29 下午 1:39
 * @Version 1.0
 **/
public class DiscardServer {
    private int port;

    public DiscardServer(int port) {
        this.port = port;
    }

    public void run() throws Exception{
        EventLoopGroup bossGroup = new NioEventLoopGroup();//(1)
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();//(2)
            b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)//(3)
                .childHandler(new ChannelInitializer<SocketChannel>() {//(4)
                    @Override protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline().addLast(new DiscardHandler());
                    }
                }).option(ChannelOption.SO_BACKLOG, 128)//(5)
                .childOption(ChannelOption.SO_KEEPALIVE, true);//(6)
            //綁定端口硕噩,接收進(jìn)來(lái)的連接
            ChannelFuture f = b.bind(port).sync();//(7)
            //等待服務(wù)器的socket關(guān)閉
            //在本例中假残,這不會(huì)發(fā)生,但你可以優(yōu)雅地關(guān)閉你的服務(wù)
            f.channel().closeFuture().sync();

        }finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        int port = 8080;
        if(args.length > 0){
            port = Integer.parseInt(args[0]);
        }
        new DiscardServer(port).run();
    }
}
  1. NioEventLoopGroup是一個(gè)用于處理IO操作的多線程事件循環(huán)炉擅。Netty為不同的傳輸類型實(shí)現(xiàn)了多樣的EventLoopGroup辉懒。我們?cè)诒纠袑?shí)現(xiàn)的服務(wù)器端應(yīng)用,使用了兩個(gè)NioEventLoopGroup谍失。其一眶俩,通常稱為boss,接受一個(gè)進(jìn)來(lái)的連接快鱼;其二颠印,通常稱為worker纲岭,處理boss循環(huán)器已經(jīng)接受并注冊(cè)到worker中的連接。多少個(gè)線程线罕,以及線程和Channel之間的映射取決于EventLoopGroup的實(shí)現(xiàn)止潮,或者通過(guò)構(gòu)造器配置。
  2. ServerBootstrap是一個(gè)用于配置服務(wù)器的幫助類钞楼。你可以使用channel直接配置服務(wù)器喇闸。然而,這是一個(gè)乏味的過(guò)程询件,在大多數(shù)情況下你不需要做燃乍。
  3. 在此處,我們指明使用NioServerSocketChannel類來(lái)實(shí)例化一個(gè)新的Channel來(lái)接受進(jìn)來(lái)的連接宛琅。
  4. 此處指明的處理器總是由新接受的channel來(lái)評(píng)估橘沥。(The handler specified here will always be evaluated by a newly accepted Channel.)ChannelInitializer是一個(gè)特殊的處理器,它被用于幫助用戶初始化一個(gè)新的channel夯秃。類似于你想通過(guò)添加一些處理器到channel的ChannelPipeline以完成初始化座咆。
  5. 你還能夠設(shè)置參數(shù)來(lái)定制化你的Channel實(shí)現(xiàn)。本例實(shí)現(xiàn)的是TCP/IP服務(wù)器仓洼,因此可以設(shè)置socket options例如tcpNoDelaykeepAlive介陶。
  6. option()是服務(wù)于NioServerSocketChannel,接受進(jìn)來(lái)的連接色建。而childOption()則是服務(wù)于父ServerChannel接受的Channels哺呜。
  7. 最后,綁定端口然后開啟服務(wù)箕戳。

測(cè)試結(jié)果
我們使用cmd某残,輸入命令talnet localhost 8080發(fā)起請(qǐng)求,輸入1陵吸,2玻墅,3,4壮虫,控制臺(tái)依次打印出來(lái)澳厢。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市囚似,隨后出現(xiàn)的幾起案子剩拢,更是在濱河造成了極大的恐慌,老刑警劉巖饶唤,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件徐伐,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡募狂,警方通過(guò)查閱死者的電腦和手機(jī)办素,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門魏保,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人摸屠,你說(shuō)我怎么就攤上這事谓罗。” “怎么了季二?”我有些...
    開封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵檩咱,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我胯舷,道長(zhǎng)刻蚯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任桑嘶,我火速辦了婚禮炊汹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘逃顶。我一直安慰自己讨便,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開白布以政。 她就那樣靜靜地躺著霸褒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪盈蛮。 梳的紋絲不亂的頭發(fā)上废菱,一...
    開封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音抖誉,去河邊找鬼殊轴。 笑死,一個(gè)胖子當(dāng)著我的面吹牛袒炉,可吹牛的內(nèi)容都是我干的旁理。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼梳杏,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼韧拒!你這毒婦竟也來(lái)了淹接?” 一聲冷哼從身側(cè)響起十性,我...
    開封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎塑悼,沒想到半個(gè)月后劲适,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡厢蒜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年霞势,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了烹植。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡愕贡,死狀恐怖草雕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情固以,我是刑警寧澤墩虹,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站憨琳,受9級(jí)特大地震影響诫钓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜篙螟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一菌湃、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧遍略,春花似錦惧所、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至寞忿,卻和暖如春驰唬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背腔彰。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工叫编, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人霹抛。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓搓逾,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親杯拐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子霞篡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容