netty同步獲取response

前言

最近在用netty開(kāi)發(fā)項(xiàng)目慷嗜,主要用于tcp通信穷缤,處理邏輯時(shí)發(fā)現(xiàn)沒(méi)有很好的同步獲取response的機(jī)制为迈,研究了一下現(xiàn)在主流的方式三椿,就自定義實(shí)現(xiàn)了一下。

SyncHttpResponse

這里以http服務(wù)為例葫辐,tcp的協(xié)議可以類似使用搜锰,完整的代碼還是放在Github上了。

  1. 定義ClientHandler耿战,繼承了ChannelInboundHandlerAdapter蛋叼,并保存了ChannelHandlerContext來(lái)實(shí)現(xiàn)發(fā)送請(qǐng)求的功能。
    同步主要是用到了ChannelPromise剂陡,發(fā)送完請(qǐng)求后狈涮,會(huì)新生成一個(gè)ChannelPromise并返回租冠,并在接收到完整的response后setSuccess
    public static class ClientHandler extends ChannelInboundHandlerAdapter {
        private ChannelHandlerContext ctx;
        private ChannelPromise promise;
        private String data;
        private long readByte;
        private long contentLength;
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            super.channelActive(ctx);
            this.ctx = ctx;
        }
        public ChannelPromise sendMessage(Object message) {
            if (ctx == null)
                throw new IllegalStateException();
            promise = ctx.writeAndFlush(message).channel().newPromise();
            return promise;
        }
        public String getData() {
            return data;
        }
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            if (msg instanceof HttpResponse) {
                HttpResponse response = (HttpResponse) msg;
                contentLength = Long.parseLong(response.headers().get(HttpHeaders.Names.CONTENT_LENGTH));
                readByte = 0;
            }
            if (msg instanceof HttpContent) {
                HttpContent content = (HttpContent) msg;
                ByteBuf buf = content.content();
                readByte += buf.readableBytes();
                data += buf.toString(Charset.forName("gb2312"));
                if (readByte >= contentLength) {
                    promise.setSuccess();
                }
                buf.release();
            }
        }
    }
  1. client薯嗤,這里開(kāi)啟一個(gè)Bootstrap顽爹,內(nèi)置了HttpRequestEncoderHttpResponseDecoder來(lái)實(shí)現(xiàn)http的decode和encode。connect方法會(huì)鏈接到指定的host骆姐,這里會(huì)有一個(gè)死循環(huán)镜粤,直到鏈接激活為止。getBody方法會(huì)在發(fā)送HttpRequest后await到ChannelPromise的完成玻褪,然后取出讀到的數(shù)據(jù)肉渴。
    public static class HttpClient {
        private ClientHandler clientHandler = new ClientHandler();
        private String url;
        private URI uri;
        public HttpClient(String url) {
            this.url = url;
        }
        public void connect() throws Exception {
            uri = new URI(url);
            EventLoopGroup loopGroup = new NioEventLoopGroup();
            Bootstrap b = new Bootstrap();
            b.group(loopGroup).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(new HttpRequestEncoder()).addLast(new HttpResponseDecoder()).addLast(clientHandler);
                }
            });
            Channel channel = b.connect(uri.getHost(), uri.getPort() < 0 ? 80 : uri.getPort()).sync().channel();
            while (!channel.isActive()) {
                Thread.sleep(1000);
            }
        }
        public String getBody() throws Exception {
            DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uri.toASCIIString());
            request.headers().set(HttpHeaders.Names.HOST, uri.getHost());
            request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
            request.headers().set(HttpHeaders.Names.CONTENT_LENGTH, request.content().readableBytes());
            ChannelPromise promise = clientHandler.sendMessage(request);
            promise.await();
            return clientHandler.getData();
        }
    }
  1. 程序入口。
    public class SyncHttpResponse {
        public static void main(String[] args) throws Exception {
            HttpClient client = new HttpClient("http://www.baidu.com");
            client.connect();
            System.out.println(client.getBody());
        }
    }

運(yùn)行程序就會(huì)打印出response的內(nèi)容了带射。

結(jié)語(yǔ)

netty是異步io框架同规,理論上不提倡同步的處理,但是某些情況下強(qiáng)依賴同步的結(jié)果窟社,可以采用這種方式券勺。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市灿里,隨后出現(xiàn)的幾起案子关炼,更是在濱河造成了極大的恐慌,老刑警劉巖匣吊,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件儒拂,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡色鸳,警方通過(guò)查閱死者的電腦和手機(jī)社痛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)命雀,“玉大人蒜哀,你說(shuō)我怎么就攤上這事∮酱疲” “怎么了凡怎?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)赊抖。 經(jīng)常有香客問(wèn)我统倒,道長(zhǎng),這世上最難降的妖魔是什么氛雪? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任房匆,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘浴鸿。我一直安慰自己井氢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布岳链。 她就那樣靜靜地躺著花竞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掸哑。 梳的紋絲不亂的頭發(fā)上约急,一...
    開(kāi)封第一講書(shū)人閱讀 49,730評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音苗分,去河邊找鬼厌蔽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛摔癣,可吹牛的內(nèi)容都是我干的奴饮。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼择浊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼戴卜!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起近她,我...
    開(kāi)封第一講書(shū)人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤叉瘩,失蹤者是張志新(化名)和其女友劉穎膳帕,沒(méi)想到半個(gè)月后粘捎,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡危彩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年攒磨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片汤徽。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡娩缰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出谒府,到底是詐尸還是另有隱情拼坎,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布完疫,位于F島的核電站泰鸡,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏壳鹤。R本人自食惡果不足惜盛龄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧余舶,春花似錦啊鸭、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至挟憔,卻和暖如春憎妙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背曲楚。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工厘唾, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人龙誊。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓抚垃,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親趟大。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鹤树,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

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

  • netty常用API學(xué)習(xí) netty簡(jiǎn)介 Netty是基于Java NIO的網(wǎng)絡(luò)應(yīng)用框架. Netty是一個(gè)NIO...
    花丶小偉閱讀 5,995評(píng)論 0 20
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)逊朽,斷路器罕伯,智...
    卡卡羅2017閱讀 134,626評(píng)論 18 139
  • 6.2 Channel實(shí)現(xiàn) ![Netty_Channel類圖][2] Channel的類圖比較清晰。我們主要分析...
    Hypercube閱讀 8,512評(píng)論 6 19
  • RPC框架遠(yuǎn)程調(diào)用的實(shí)現(xiàn)方式在原理上是比較簡(jiǎn)單的叽讳,即將調(diào)用的方法(接口名追他、方法名、參數(shù)類型岛蚤、參數(shù))序列化之后發(fā)送到...
    謎碌小孩閱讀 3,088評(píng)論 0 13
  • 新建文章 運(yùn)行 生成靜態(tài)文件 上傳到網(wǎng)站
    Micason閱讀 219評(píng)論 0 0