<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] # 服務端啟動的demo **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.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.util.AttributeKey; public class Server { public static void main(String[] args) { //服務端接收客戶端連接的線程,accept NioEventLoopGroup bossGroup = new NioEventLoopGroup(1); //客戶端發送消息給服務端的線程 NioEventLoopGroup workerGroup = new NioEventLoopGroup(); try { //這個里面是空的,什么也不做 ServerBootstrap b = new ServerBootstrap(); //把這2個線程配置進去 b.group(bossGroup, workerGroup) //設置socketChannel .channel(NioServerSocketChannel.class) //設置客戶端連接設置tcp的屬性 .childOption(ChannelOption.TCP_NODELAY, true) //每次創建客戶端連接的時候綁定些基本屬性 .childAttr(AttributeKey.newInstance("childAttr"), "childAttrValue") //服務端啟動過程中哪些邏輯,這邊我寫的只是打印出來 //這個handler主要是accept用戶的連接 .handler(new ServerHandler()) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { //配置數據流讀寫的處理邏輯.會配置很多 // ch.pipeline().addLast(); //... } }); //綁定端口 ChannelFuture f = b.bind(8888).sync(); f.channel().closeFuture().sync(); } catch (Exception e) { e.printStackTrace(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } } ~~~ **ServerHandler類** ~~~ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import java.util.concurrent.TimeUnit; /** * 主要是accept用戶的連接 */ public class ServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) { System.out.println("channelActive"); } @Override public void channelRegistered(ChannelHandlerContext ctx) { System.out.println("channelRegistered"); } @Override public void handlerAdded(ChannelHandlerContext ctx) { System.out.println("handlerAdded"); } @Override public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception { super.channelRead(ctx, msg); new Thread(new Runnable() { @Override public void run() { // 耗時的操作 String result = loadFromDB(); ctx.channel().writeAndFlush(result); ctx.executor().schedule(new Runnable() { @Override public void run() { // ... } }, 1, TimeUnit.SECONDS); } }).start(); } private String loadFromDB() { return "hello world!"; } } ~~~ # 服務端啟動流程 * 創建服務端Channel 調用JDK底層API的jdk的channel,把他包裝成自己的channel,同時創建一些基本組件綁定在自己的channel上面 * 初始化服務端Channel 初始化一些基本屬性,添加邏輯處理器器 * 注冊selector 將底層的Channel注冊到底層的selector輪詢器上面,把服務端channel作為一個daragram綁定在jdk底層的channel上面,事件輪詢有數據來的時候直接拿daragram * 端口綁定 調用jdk底層的API,綁定端口 ## 創建服務端Channel ~~~ --bind()[用戶代碼入口] | |--initAndRegister()初始化并注冊 | |--newChannel()[創建服務端channel] ~~~ bind()我們一直跟進去會發現調用doBind()方法 在doBind()方法里面發現有 initAndRegister()這個方法這個就是創建服務端的channel方法 到initAndRegister()這個方法里面這里就是創建服務端channel ~~~ //創建服務端channel channel = channelFactory.newChannel(); //初始化channel init(channel); ~~~ 這邊是newChannel(),我們到ReflectiveChannelFactory這個類里面看 ~~~ public T newChannel() { try { return clazz.newInstance(); ~~~ 他是反射創建的,那么我們就要看channelFactory了 這個channelFactory在哪里初始化的,又傳了哪些channelFactory? 我們回到業務代碼那邊的.channel(NioServerSocketChannel.class)點channel進去 ~~~ return channelFactory(new ReflectiveChannelFactory<C>(channelClass)); ~~~ channelFactory沒做什么事情只是把他原路返回 參數channelClass就是傳進來的NioServerSocketChannel 看到他會把這個傳進來的進行反射創建channel 那么我們現在要看下NioServerSocketChannel做了什么事情 ## 反射創建服務端Channel ~~~ newSocket()[通過jdk來創建底層jdk channel] | | NioServerSocketChannelConfig()[tcp參數配置類] | | AbstractNioChannel() | |--configureBlocking(false)[阻塞模式] | |--AbstractChannel()[創建id,unsafe,pipeline] ~~~ 我們來看NioServerSocketChannel源碼 ~~~ public NioServerSocketChannel() { this(newSocket(DEFAULT_SELECTOR_PROVIDER)); } ~~~ 然后點newSocket進去,發現 ~~~ return provider.openServerSocketChannel(); ~~~ 這就是調用jdk底層的創建ServerSocketChannel 這個NioServerSocketChannel構造方法創建完畢會調用這個 ~~~ public NioServerSocketChannel(ServerSocketChannel channel) { super(null, channel, SelectionKey.OP_ACCEPT); config = new NioServerSocketChannelConfig(this, javaChannel().socket()); } ~~~ 他會把jdk創建好的ServerSocketChannel傳遞進去,就是這邊的形參this 如果以后想對這個channel的tcp參數獲取可以用NioServerSocketChannelConfig這個 然后我們看上面一行 ~~~ super(null, channel, SelectionKey.OP_ACCEPT); ~~~ super一層層點上去發現AbstractNioChannel里面有這行 ~~~ ch.configureBlocking(false); ~~~ 這行就是設置服務端的channel是非阻塞的 然后我們看 ~~~ AbstractChannel()[創建id,unsafe,pipeline] ~~~ AbstractChannel就是對channel的一個抽象, 服務端,客戶端的channel都是繼承這個的 這個id就是channel的唯一標識,unsafe是tcp相關的讀寫,pipeline是處理的邏輯鏈 ~~~ protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) { super(parent); ~~~ 點這個super到上一層,發現 ~~~ protected AbstractChannel(Channel parent) { this.parent = parent; id = newId(); unsafe = newUnsafe(); pipeline = newChannelPipeline(); } ~~~ 這些就是設置那幾個參數 ## 初始化服務端channel ~~~ init()[初始化入口] | |--set ChannelOptions,ChannelAttrs | |--set ChildOptions, ChildAttrs | |--config handler[配置服務端pipeline] | |--add ServerBootstrapAcceptor[添加連接器] ~~~ 我們從業務層的bind跟進去到dobind方法 然后發現這行 ~~~ final ChannelFuture regFuture = initAndRegister(); ~~~ initAndRegister里面有個init方法,我們用command+option+b找到實現類 ~~~ void init(Channel channel) throws Exception { final Map<ChannelOption<?>, Object> options = options0(); synchronized (options) { channel.config().setOptions(options); } ~~~ 這就是把我們綁定的channel設置進去,下面也是一樣 在這個方法里面在往下看 ~~~ synchronized (childOptions) { currentChildOptions = childOptions.entrySet().toArray(newOptionArray(childOptions.size())); } synchronized (childAttrs) { currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size())); } ~~~ 這就是把ChildOptions, ChildAttrs 保存到currentChildOptions和currentChildAttrs這2個局部變量 這個方法往下看 ~~~ p.addLast ~~~ 拿到服務端的pipeline,配置服務端pipeline ~~~ config.handler(); ~~~ 把用戶自定義的handler添加進去 handler就是把他保存為bootstrap的變量,然后在外面 ~~~ pipeline.addLast(handler); ~~~ 用這樣的方法把用戶的邏輯處理鏈添加進去 然后netty會把一個特殊的channelhandle(添加連接器),他會在你啟動的時候添加一個特殊的處理器 還是那個方法往下看 ~~~ pipeline.addLast(new ServerBootstrapAcceptor( currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs)); ~~~ 在構造ServerBootstrapAcceptor的時候會把前面設置的currentChildOptions和currentChildAttrs和用戶代碼里面配置的childHandler對應currentChildHandler currentChildGroup就是用戶代碼里面的group # 服務端socket在哪里初始化? # 在哪里accept連接?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看