国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

慕課網(wǎng)_《Netty入門之WebSocket初體驗》學(xué)習(xí)總結(jié)

Noodles / 1499人閱讀

時間:2018年04月11日星期三
說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):https://www.imooc.com
教學(xué)源碼:https://github.com/zccodere/s...
學(xué)習(xí)源碼:https://github.com/zccodere/s...

第一章:課程介紹 1-1 課程介紹

什么是Netty

高性能、事件驅(qū)動、異步非阻塞的IO Java開源框架

基于NIO的客戶端,服務(wù)端編程框架

非常可靠的穩(wěn)定性和伸縮性

Netty使用場景

高性能領(lǐng)域:游戲、大數(shù)據(jù)、分布式計算

多線程并發(fā)領(lǐng)域:多線程模型、主從多線程模型

異步通信領(lǐng)域:異步非阻塞,主動獲取或通過通知機制來得到結(jié)果

課程提綱

IO通信:BIO、偽異步IO、NIO、AIO通信

Netty入門:原生NIO的缺陷、Netty的優(yōu)勢

WebSocket入門:什么是WebSocket、如何建立連接、生命周期及關(guān)閉

Netty實現(xiàn)WebSocket通信案例

課程要求

有一定的Java基礎(chǔ)

有一定的IO編程基礎(chǔ)

了解Java的BIO、偽異步IO、NIO和AIO

第二章:IO通信 2-1 IO通信

BIO通信

一個線程負責(zé)連接

一請求一應(yīng)答

缺乏彈性伸縮能力

BIO通信模型

偽異步IO通信

線程池負責(zé)連接

M請求N應(yīng)答

線程池阻塞

偽異步IO通信模型

NIO通信

緩沖區(qū)Buffer

通道Channel

多路復(fù)用器Selector

AIO通信

連接注冊讀寫事件和回調(diào)函數(shù)

讀寫方法異步

主動通知程序

四種IO對比

第三章:Netty入門 3-1 Netty入門

原生NIO的缺陷

類庫和API繁雜

入門門檻高

工作量和難度大

JDK NIO存在BUG

Netty的優(yōu)勢

API使用簡單,定制能力強,可以通過ChannelHandler對框架進行靈活的擴展

入門門檻低,功能強大,預(yù)制了多種編解碼功能,支持多種主流協(xié)議

性能高,通過與其他的業(yè)界主流的NIO框架對比,Netty的綜合性能最優(yōu)

Netty比較成熟穩(wěn)定,Netty修復(fù)了JDK NIO所有發(fā)現(xiàn)的BUG

第四章:WebSocket入門 4-1 WebSocket入門

什么是WebSocket

H5協(xié)議規(guī)范:H5提出的協(xié)議規(guī)范

握手機制:使客戶端與服務(wù)器能夠建立類似TCP的連接,方便通信

解決客戶端與服務(wù)端實時通信而產(chǎn)生的技術(shù):基于TCP的協(xié)議

WebSocket的優(yōu)點

節(jié)省通信開銷:以前使用輪詢,開銷較大

服務(wù)器主動傳送數(shù)據(jù)給客戶端:任意時刻,相互傳送數(shù)據(jù)

實時通信:可以彼此相互推送信息

WebSocket建立連接

客戶端發(fā)起握手請求

服務(wù)器響應(yīng)請求

連接建立

WebSocket生命周期

打開事件:發(fā)生新的連接時調(diào)用、在端點上建立連接時且在任何事件之前

消息事件:接收WebSocket對話中,另一端發(fā)送的消息

錯誤事件:在進行連接或端點發(fā)生錯誤時產(chǎn)生

關(guān)閉事件:表示W(wǎng)ebSocket端點的連接關(guān)閉

WebSocket關(guān)閉連接

服務(wù)器關(guān)閉底層TCP連接

客戶端發(fā)起TCP Close

第五章:通信案例 5-1 通信案例

基于Netty實現(xiàn)WebSocket通信案例

功能介紹

Netty開發(fā)服務(wù)端

Html實現(xiàn)客戶端

實現(xiàn)服務(wù)端與客戶端的實時交互

代碼編寫

1.創(chuàng)建名為netty-websocket的maven工程pom如下



    4.0.0

    com.myimooc
    netty-websocket
    0.0.1-SNAPSHOT

    
        
            io.netty
            netty-all
            5.0.0.Alpha1
        
    

    
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                
                    1.8
                    1.8
                    UTF-8
                
            
        
    
    

2.編寫NettyConfig類

package com.myimooc.netty.websocket;

import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;

/**
 * 
* 標題: Netty 全局配置類
* 描述: 存儲整個工程的全局配置
* * @author zc * @date 2018/04/11 */ public class NettyConfig { /** * 存儲每一個客戶端接入進來時的 Channel */ public static ChannelGroup group = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); }

3.編寫MyWebSocketHandler類

package com.myimooc.netty.websocket;

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

import java.util.Date;

/**
 * 
* 標題: 處理客戶端WebSocket請求的核心業(yè)務(wù)處理類
* 描述: 接收/處理/響應(yīng) 客戶端websocket請求的核心業(yè)務(wù)處理類
* * @author zc * @date 2018/04/11 */ public class MyWebSocketHandler extends SimpleChannelInboundHandler { private WebSocketServerHandshaker handshaker; private static final String WEB_SOCKET_URL = "ws://localhost:8888/websocket"; /** * 服務(wù)端處理客戶端websocket請求的核心方法 */ @Override protected void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception { if (msg instanceof FullHttpRequest) { // 處理客戶端向服務(wù)端發(fā)起http握手請求的業(yè)務(wù) FullHttpRequest request = (FullHttpRequest) msg; this.handHttpRequest(ctx, request); } else if (msg instanceof WebSocketFrame) { // 處理websocket連接的業(yè)務(wù) WebSocketFrame frame = (WebSocketFrame) msg; this.handWebSocketFrame(ctx, frame); } } /** * 處理客戶端與服務(wù)端之前的websocket業(yè)務(wù) */ private void handWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) { if (frame instanceof CloseWebSocketFrame){ // 如果是關(guān)閉websocket的指令 handshaker.close(ctx.channel(),(CloseWebSocketFrame)frame.retain()); } if (frame instanceof PingWebSocketFrame){ // 如果是ping消息 ctx.channel().write(new PongWebSocketFrame(frame.content().retain())); return; } if (!(frame instanceof TextWebSocketFrame)){ // 如果不是文本消息,則拋出異常 System.out.println("目前暫不支持二進制消息"); throw new RuntimeException("【"+this.getClass().getName()+"】不支持二進制消息"); } // 獲取客戶端向服務(wù)端發(fā)送的文本消息 String request = ((TextWebSocketFrame) frame).text(); System.out.println("服務(wù)端收到客戶端的消息=====>>>" + request); // 將客戶端發(fā)給服務(wù)端的消息返回給客戶端 TextWebSocketFrame tws = new TextWebSocketFrame(new Date().toString() + ctx.channel().id() + "====>>>" + request); // 群發(fā),服務(wù)端向每個連接上來的客戶端群發(fā)消息 NettyConfig.group.writeAndFlush(tws); } /** * 處理客戶端向服務(wù)端發(fā)起http握手請求的業(yè)務(wù) */ private void handHttpRequest(ChannelHandlerContext ctx, FullHttpRequest request) { if (!request.getDecoderResult().isSuccess() || !("websocket").equals(request.headers().get("Upgrade"))) { // 不是websocket握手請求時 this.sendHttpResponse(ctx, request, new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST)); return; } WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(WEB_SOCKET_URL, null, false); handshaker = wsFactory.newHandshaker(request); if (handshaker == null) { WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel()); } else { handshaker.handshake(ctx.channel(), request); } } /** * 服務(wù)端向客戶端響應(yīng)消息 */ private void sendHttpResponse(ChannelHandlerContext ctc, FullHttpMessage request, DefaultFullHttpResponse response) { if (response.getStatus().code() != 200) { ByteBuf buf = Unpooled.copiedBuffer(response.getStatus().toString(), CharsetUtil.UTF_8); response.content().writeBytes(buf); buf.release(); } // 服務(wù)端向客戶端發(fā)送數(shù)據(jù) ChannelFuture future = ctc.channel().writeAndFlush(response); if (response.getStatus().code() != 200) { future.addListener(ChannelFutureListener.CLOSE); } } /** * 工程出現(xiàn)異常時調(diào)用 */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } /** * 客戶端與服務(wù)端創(chuàng)建連接時調(diào)用 */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { NettyConfig.group.add(ctx.channel()); System.out.println("客戶端與服務(wù)端連接開啟..."); } /** * 客戶端與服務(wù)端斷開連接時調(diào)用 */ @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { NettyConfig.group.remove(ctx.channel()); System.out.println("客戶端與服務(wù)端連接關(guān)閉..."); } /** * 服務(wù)端接收客戶端發(fā)送過來的數(shù)據(jù)結(jié)束之后調(diào)用 */ @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } }

4.編寫MyWebSocketChannelHandler類

package com.myimooc.netty.websocket;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.stream.ChunkedWriteHandler;


/**
 * 
* 標題: 初始化連接時的各個組件
* 描述: 初始化連接時的各個組件
* * @author zc * @date 2018/04/11 */ public class MyWebSocketChannelHandler extends ChannelInitializer { @Override protected void initChannel(SocketChannel ch) throws Exception { // 將請求和應(yīng)答消息解碼為HTTP消息 ch.pipeline().addLast("http-codec",new HttpServerCodec()); // 將HTTP消息的多個部分合成一條完整的HTTP消息 ch.pipeline().addLast("aggregator",new HttpObjectAggregator(65536)); // 向客戶端發(fā)送HTML5文件 ch.pipeline().addLast("http-chunked", new ChunkedWriteHandler()); ch.pipeline().addLast("handler",new MyWebSocketHandler()); } }

5.編寫AppStart類

package com.myimooc.netty.websocket;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

/**
 * 
* 標題: 程序入口
* 描述: 啟動應(yīng)用
* * @author zc * @date 2018/04/11 */ public class AppStart { public static void main(String[] args) { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup,workGroup); serverBootstrap.channel(NioServerSocketChannel.class); serverBootstrap.childHandler(new MyWebSocketChannelHandler()); System.out.println("服務(wù)端開啟等待客戶端連接..."); Channel channel = serverBootstrap.bind(8888).sync().channel(); channel.closeFuture().sync(); }catch (Exception e){ e.printStackTrace(); }finally { // 優(yōu)雅的退出程序 bossGroup.shutdownGracefully(); workGroup.shutdownGracefully(); } } }

6.編寫websocket.html




    
    
    WebSocket客戶端

    







客戶端接收到服務(wù)端返回的應(yīng)答消息

第六章:課程總結(jié) 6-1 課程總結(jié)

課程總結(jié)

課程介紹

IO通信:四種IO通信

Netty入門:原生NIO的缺點,Netty的優(yōu)點

WebSocket入門:WebSocket的優(yōu)點,如何使用

通信案例:Netty實現(xiàn)WebSocket通信案例

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/69093.html

相關(guān)文章

  • WebSocket就是這么簡單

    摘要:是一個持久化的協(xié)議,相對于這種非持久的協(xié)議來說。最大的特點就是實現(xiàn)全雙工通信客戶端能夠?qū)崟r推送消息給服務(wù)端,服務(wù)端也能夠?qū)崟r推送消息給客戶端。參考鏈接知乎問題原理原理知乎問題編碼什么用如果文章有錯的地方歡迎指正,大家互相交流。 前言 今天在慕課網(wǎng)上看到了Java的新教程(Netty入門之WebSocket初體驗):https://www.imooc.com/learn/941 WebS...

    hikui 評論0 收藏0
  • 課網(wǎng)_《第一個docker化的java應(yīng)用》學(xué)習(xí)總結(jié)

    摘要:時間年月日星期四說明本文部分內(nèi)容均來自慕課網(wǎng)。倉庫構(gòu)建鏡像的目的是為了在其機器上運行鏡像程序。使用參數(shù),冒號前面為主機端口,后面為容器端口。 時間:2017年04月27日星期四說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)示例源碼:無個人學(xué)習(xí)源碼:無 第一章:課程介紹 1-1 課程介紹 Docker能火的原因 快速的持續(xù)集成 服務(wù)的彈性伸縮 部署...

    李濤 評論0 收藏0

發(fā)表評論

0條評論

Noodles

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<