netty學(xué)習(xí)筆記(一) -- 創(chuàng)建一個(gè)簡單的客戶端服務(wù)器通信實(shí)例

完全是零基礎(chǔ)開始的后端開發(fā)吨掌,所以該系列筆記(或者稱為教程也可以)是完全假設(shè)沒有任何預(yù)備知識的,但是前提是:1. Java基礎(chǔ);2. maven配置知識(gradle);

環(huán)境配置

本項(xiàng)目基于maven進(jìn)行學(xué)習(xí)啟動(dòng)析砸,我們需要用到的工具和依賴:

  • maven安裝與配置(詳見上一篇)
  • eclipe(IDE for Java web)
  • JDK 1.7 +
  • netty latest (netty download)
  • telnet(linux/unix 默認(rèn)可用,windows需配置)

配置十分容易爆袍,就是將相關(guān)的jar包放置到lib目錄中首繁,同時(shí)在pom.xml中添加依賴即可。


項(xiàng)目結(jié)構(gòu)

在pom.xml中添加依賴如下:

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>5.0.0.Alpha2</version>
</dependency>

項(xiàng)目說明

此次教程旨在通過netty搭建一個(gè)本地服務(wù)器陨囊,采用telnet連接的方式實(shí)現(xiàn)向服務(wù)端口發(fā)送消息弦疮,驗(yàn)證客戶端和服務(wù)器的連通性,在服務(wù)端實(shí)時(shí)打印出客戶端發(fā)送過來的信息蜘醋,借此對netty的用法有一個(gè)初步的理解胁塞。
同時(shí)為了進(jìn)階netty,還有以下資料參考:
先扔幾個(gè)參考學(xué)習(xí)的網(wǎng)頁:

netty 官方API: netty link

netty 中文指南:netty 中文

netty 優(yōu)秀博客netty 入門

關(guān)于NIO基礎(chǔ)的知識:

https://my.oschina.net/andylucc/blog/614295
http://www.cnblogs.com/dolphin0520/p/3919162.html 
http://blog.csdn.net/wuxianglong/article/details/6604817

服務(wù)代碼構(gòu)建

服務(wù)器的作用是根據(jù)客戶端發(fā)送過來的信息進(jìn)行解析后執(zhí)行對應(yīng)的事務(wù)處理策略压语,姑且我們將這個(gè)稱之為“事務(wù)策略”闲先。
不同的事務(wù)策略是為了滿足客戶端各種請求(比如:數(shù)據(jù)庫增刪改查、文件上傳下載等)无蜂,而通過定義協(xié)議,通過特定的請求字段及參數(shù)等蒙谓,發(fā)送到服務(wù)器進(jìn)行特定事務(wù)的執(zhí)行并返回結(jié)果斥季。

在本例中,則通過一個(gè)簡單的事務(wù)策略實(shí)例-打印客戶端消息

創(chuàng)建打印客戶端消息的事務(wù)策略

package geekfish.NettyServer;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil;

public class SimpleServerTestHandler extends ChannelHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // get the msg from clients
        try {
            ByteBuf in = (ByteBuf) msg;
            System.out.println("the msg from client is :" + in.toString(CharsetUtil.UTF_8) + " from "
                    + ctx.hashCode());
        } finally {
            // 我們必須要對引用計(jì)數(shù)的對象進(jìn)行手動(dòng)釋放
            ReferenceCountUtil.release(msg);
        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        // TODO Auto-generated method stub
        super.channelReadComplete(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // TODO Auto-generated method stub
        super.exceptionCaught(ctx, cause);
    }
}

如我們之前所說酣倾,當(dāng)客戶端發(fā)送特定的請求時(shí)舵揭,我們在服務(wù)器端接收到客戶端報(bào)文后并進(jìn)行解析從而確定選用哪一個(gè)事務(wù)策略,在此我們引入兩個(gè)問題:

  • 如何制定請求類型和在服務(wù)器端解析

在此躁锡,我們簡化了流程午绳,只要客戶端與服務(wù)器建立了連接,那么服務(wù)器就會(huì)將客戶端發(fā)送過來的信息無腦地打印出來映之,并不涉及多業(yè)務(wù)類型的解析拦焚;

  • 誰來負(fù)責(zé)接收并處理客戶端信息

因此,僅有一個(gè)事務(wù)策略肯定是不夠的杠输,需要有主體去執(zhí)行才行赎败,可以想象這個(gè)主體主要負(fù)責(zé)的工作:接收所有客戶端信息、解析客戶端信息蠢甲、執(zhí)行客戶端請求的任務(wù)僵刮、返回執(zhí)行結(jié)果給客戶端。所以我們還有一個(gè)主體需要實(shí)現(xiàn)鹦牛,這里我們姑且將之稱為“服務(wù)端主體”搞糕。

創(chuàng)建服務(wù)端主體

package geekfish.NettyServer;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
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;

public class MainServer {
    private int port;

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

    public void run() throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        System.out.println("ready to run port =>" + port);
        try {
            // 我們需要?jiǎng)?chuàng)建一個(gè)ServerBootstrap啟動(dòng)NIO服務(wù)
            ServerBootstrap bootstrap = new ServerBootstrap();
            // 我們需要設(shè)置boss Group 和 worker Group
            bootstrap = bootstrap.group(bossGroup, workerGroup);
            // 設(shè)置channel
            bootstrap = bootstrap.channel(NioServerSocketChannel.class);
            // 我們通過增加pipeline的方式給channel增加事務(wù)處理監(jiān)聽
            bootstrap = bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {

                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    // 我們可以在此處增加各種事務(wù)處理的監(jiān)聽,比如xxxServerHandler
                    ch.pipeline().addLast(new SimpleServerTestHandler());
                    // you can still add other handlers here
                }
            });

            // 我們可以在此處進(jìn)行參數(shù)的設(shè)置
            bootstrap = bootstrap.option(ChannelOption.SO_BACKLOG, 128);
            // 設(shè)置子連接的參數(shù)
            bootstrap = bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
            // 綁定端口并啟動(dòng)接收客戶端信息
            ChannelFuture channelFuture = bootstrap.bind(port).sync();
            // 一直等待循環(huán)接收信息直到socket關(guān)閉
            channelFuture.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
    
    //the main entrance to run this instance
    public final static void main(String[] args) throws Exception{
        int port = 8080;
        if(args.length > 0)
            port = Integer.parseInt(args[0]);
        new MainServer(port).run();
        System.out.println("the server start listening...");
    }
}

代碼驗(yàn)證測試

到此為止曼追,簡化版的項(xiàng)目已經(jīng)基本完成窍仰,現(xiàn)在既可以通過talnet連接進(jìn)行簡單會(huì)話測試。

  • 啟動(dòng)運(yùn)行 服務(wù)端主體拉鹃;

run MainServer,當(dāng)然此處你可以帶上端口號參數(shù)辈赋,如果懶到啥都不干,那就是8080了膏燕,記住這個(gè)端口號钥屈,因?yàn)榭蛻舳诵枰c這個(gè)端口創(chuàng)建連接;

  • 在terminal中創(chuàng)建連接坝辫;
telnet localhost 8080

當(dāng)然這里的8080需要替換為你當(dāng)前啟動(dòng)的端口號篷就,當(dāng)連接創(chuàng)建之后,則可以在terminal會(huì)話窗口內(nèi)向服務(wù)端發(fā)送消息啦近忙,此時(shí)打開eclipse的控制臺就可以看到每一條從客戶端發(fā)過來的信息竭业。

如果使用的是windows,注意windows下默認(rèn)未開啟telnet連接及舍,所以直接在cmd中輸入以上指令可能無法生效未辆,需要去到'控制面板>>程序>>打開或者關(guān)閉windows功能'里面勾選上'telnet客戶端'。

寫在最后的話

樓主是計(jì)算機(jī)視覺這塊的锯玛,所以比較偏重于應(yīng)用層咐柜,對于前后端的開發(fā)基本算是零起步兼蜈,但是通過接觸前后端開發(fā),最深的感觸就是各種各樣并且飛速迭代的框架拙友,開發(fā)者入門時(shí)可能會(huì)遇到各種選擇問題为狸,但是從樓主的經(jīng)歷來看,框架是封裝好的工具遗契,切不可不求甚解地強(qiáng)記框架API辐棒,而是要大致理解后端框架共性的業(yè)務(wù)流程及模塊劃分。

由于走過彎路牍蜂,沒有使用任何框架上來就是繼承Servlet去實(shí)現(xiàn)漾根,雖然最后堆了一坨代碼(包括自定義json封裝解析類、數(shù)據(jù)庫操作類捷兰、文件操作類等),所以即使實(shí)現(xiàn)了簡單的后臺功能立叛,但是對于高并發(fā)、數(shù)據(jù)庫高性能開發(fā)等均一無所知贡茅。然而與此同時(shí)秘蛇,因?yàn)镈IY過一個(gè)這樣簡易的結(jié)構(gòu),麻雀雖小顶考,但是也具備基本必要模塊赁还,所以在此基礎(chǔ)上,再去看各大流行框架驹沿,就會(huì)禁不住思考各個(gè)模塊對應(yīng)的實(shí)現(xiàn)細(xì)節(jié)艘策,這一點(diǎn)對上手新框架以及對現(xiàn)有框架的理解都是挺有幫助的。

最后渊季,希望這個(gè)教程能夠堅(jiān)持更新和創(chuàng)造一定的價(jià)值朋蔫。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市却汉,隨后出現(xiàn)的幾起案子驯妄,更是在濱河造成了極大的恐慌,老刑警劉巖合砂,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件青扔,死亡現(xiàn)場離奇詭異,居然都是意外死亡翩伪,警方通過查閱死者的電腦和手機(jī)微猖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缘屹,“玉大人凛剥,你說我怎么就攤上這事∏嶙耍” “怎么了犁珠?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵傅瞻,是天一觀的道長。 經(jīng)常有香客問我盲憎,道長,這世上最難降的妖魔是什么胳挎? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任饼疙,我火速辦了婚禮,結(jié)果婚禮上慕爬,老公的妹妹穿的比我還像新娘窑眯。我一直安慰自己,他們只是感情好医窿,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布磅甩。 她就那樣靜靜地躺著,像睡著了一般姥卢。 火紅的嫁衣襯著肌膚如雪卷要。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天独榴,我揣著相機(jī)與錄音僧叉,去河邊找鬼。 笑死棺榔,一個(gè)胖子當(dāng)著我的面吹牛瓶堕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播症歇,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼郎笆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了忘晤?” 一聲冷哼從身側(cè)響起宛蚓,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎德频,沒想到半個(gè)月后苍息,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡壹置,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年竞思,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钞护。...
    茶點(diǎn)故事閱讀 38,814評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盖喷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出难咕,到底是詐尸還是另有隱情课梳,我是刑警寧澤距辆,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站暮刃,受9級特大地震影響跨算,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜椭懊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一诸蚕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧氧猬,春花似錦背犯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至妄均,卻和暖如春柱锹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背丛晦。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工奕纫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人烫沙。 一個(gè)月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓匹层,卻偏偏與公主長得像,于是被迫代替她去往敵國和親锌蓄。 傳聞我的和親對象是個(gè)殘疾皇子升筏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評論 2 351

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)瘸爽,斷路器您访,智...
    卡卡羅2017閱讀 134,639評論 18 139
  • 前奏 https://tech.meituan.com/2016/11/04/nio.html 綜述 netty通...
    jiangmo閱讀 5,846評論 0 13
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司剪决,掛了不少灵汪,但最終還是拿到小米、百度柑潦、阿里享言、京東、新浪渗鬼、CVTE览露、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,218評論 11 349
  • 朋友們大家好差牛,準(zhǔn)備好了個(gè)人網(wǎng)站準(zhǔn)備發(fā)布的時(shí)候是不是都是一籌莫展命锄,萬臉懵逼?服務(wù)器都是小200一年偏化,還要準(zhǔn)備FTP脐恩?...
    cherish薯?xiàng)l閱讀 6,542評論 21 26
  • 姐姐的姐姐帶我逛旺山。 生活永遠(yuǎn)不止表面的光鮮侦讨,我一直羨慕的姐妹二人共進(jìn)退被盈,共話題,甚至共同上下班搭伤,在另...
    moitoije閱讀 161評論 0 0