Netty 快速入门系列 - Chapter 2 Netty3.x 【第五讲】 - 源码讲解

本文详细解析了Netty3.X版本的源码,重点介绍了ServerBootstrap的bind方法工作流程,从nioServerSocketChannel的初始化到Pipeline触发机制,直至Channel的绑定过程。


Netty3.X 源码: https://download.youkuaiyun.com/download/netcobol/10309152


Netty3.X 源码讲解

  
ServerBootstrap.bind(new InetSocketAddress(port))

   bind 将调用ServerBootstrap.bindAsync 方法,完成初始化 nio ServerSocketChannel,
   
   Binder通过ChannelPipeline.addLast()添加到Pipeline中,如何触发Pipeline?;


   Binder 是一个 SimpleChannelUpstreamHandler 其中关键方法是 
   
   public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) 


   根据不同的ChannelEvent,匹配不同的业务操作,这里重点关注


   如果 e 是一个 ChannelStateEvent,同时 status == OPEN


   将会调用channelOpen方法,可以通过子类实现具体的操作。


   Binder  的 channelOpen 方法:
   
   通过event 获取 Channel (ServerSocketChannel)
   evt.getChannel().bind(localAddress)




   触发Pipeline:
   
   Channel channel = getFactory().newChannel(bossPipeline); 
   
   通过Factory的 NioServerSocketChannelFactory.newChannel 触发Pipeline
   
   public ServerSocketChannel newChannel(ChannelPipeline pipeline) {
    	
        return new NioServerSocketChannel(this, pipeline, sink, bossPool.nextBoss(), workerPool);
    }
    
    构建 NioServerSocketChannel 类


    初始化 ServerSocketChannel.open() 与 socket.configureBlocking(false);


    最后调用Channels.fireChannelOpen(this),当Open Server  Socket Channel;  


    StatusEvent: ChannelState.OPEN value: Boolean.TRUE


    channel.getPipeline().sendUpstream(new UpstreamChannelStateEvent(channel, ChannelState.OPEN, Boolean.TRUE));




    然后 调用 NioServerSocketChannel.bind方法 (AbstractChannel),主要发送bind event
    
    public ChannelFuture bind(SocketAddress localAddress) {
    	
        return Channels.bind(this, localAddress);
    }
    
    Channels.bind() DownstreamChannelStateEvent status bound value: address
    channel.getPipeline().sendDownstream(new DownstreamChannelStateEvent(channel, future, ChannelState.BOUND, localAddress));


    由于PiplelineChannel sendDownstream 方法中
    如果getActualDownstreamContext 没有Downstream next (header 到头了)


    将调用sink.eventSunk方法


     NioServerSocketPipelineSink. eventSunk 方法


       Channel channel = e.getChannel();


	if (channel instanceof NioServerSocketChannel) {
		handleServerSocket(e);
	} else if (channel instanceof NioSocketChannel) {
		handleAcceptedSocket(e);
	}


      当 Channel == NioServerSocketChannel


      Event Status:BOUND


     ((NioServerBoss) channel.boss).bind(channel, future, (SocketAddress) value);




      NioServerBoss.bind 方法
     
      registerTask(new RegisterTask(channel, future, localAddress)) 其中 RegisterTask run 方法


       channel.socket.socket().bind(localAddress, channel.getConfig().getBacklog()); bind port


       call Channels.fireChannelBound() 


       channel.getPipeline().sendUpstream(new UpstreamChannelStateEvent(channel, ChannelState.BOUND, localAddress))


       channel.socket.register(selector, SelectionKey.OP_ACCEPT, channel)


       NioServerBoss.process 方法
       
       registerAcceptedChannel(channel, acceptedSocket, thread)
      
       NioWorker worker = NioServerSocketChannel.workerPool.nextWorker();
       
        worker.register(new NioAcceptedSocketChannel(parent.getFactory(), pipeline, parent, sink, acceptedSocket,
					worker, currentThread), null);


        NioAcceptedSocketChannel 构造器 调用 Channels.fireChannelOpen(this);  Channel:SocketChannel


       channel.getPipeline().sendUpstream(new UpstreamChannelStateEvent(channel, ChannelState.OPEN, Boolean.TRUE));


       NioWorker.register 方法


       Runnable task = createRegisterTask(channel, future);


        createRegisterTask 方法


      new RegisterTask((NioSocketChannel) channel, future, server);
       
       RegisterTask 构造器


       channel.channel.configureBlocking(false);
                
       channel.channel.register( selector, channel.getInternalInterestOps(), channel);   

UML 图解说


所有源码下载 :https://download.youkuaiyun.com/download/netcobol/10308871

按你说的之后C:\Users\admin\.jdks\jdk-17.0.12+7\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2024.3.6\lib\idea_rt.jar=52853" -Dfile.encoding=UTF-8 -classpath D:\UserData\Desktop\Netty和gRPC\Netty_TEST\target\classes;D:\r\io\netty\netty-all\4.1.86.Final\netty-all-4.1.86.Final.jar;D:\r\io\netty\netty-buffer\4.1.86.Final\netty-buffer-4.1.86.Final.jar;D:\r\io\netty\netty-codec\4.1.86.Final\netty-codec-4.1.86.Final.jar;D:\r\io\netty\netty-codec-dns\4.1.86.Final\netty-codec-dns-4.1.86.Final.jar;D:\r\io\netty\netty-codec-haproxy\4.1.86.Final\netty-codec-haproxy-4.1.86.Final.jar;D:\r\io\netty\netty-codec-http\4.1.86.Final\netty-codec-http-4.1.86.Final.jar;D:\r\io\netty\netty-codec-http2\4.1.86.Final\netty-codec-http2-4.1.86.Final.jar;D:\r\io\netty\netty-codec-memcache\4.1.86.Final\netty-codec-memcache-4.1.86.Final.jar;D:\r\io\netty\netty-codec-mqtt\4.1.86.Final\netty-codec-mqtt-4.1.86.Final.jar;D:\r\io\netty\netty-codec-redis\4.1.86.Final\netty-codec-redis-4.1.86.Final.jar;D:\r\io\netty\netty-codec-smtp\4.1.86.Final\netty-codec-smtp-4.1.86.Final.jar;D:\r\io\netty\netty-codec-socks\4.1.86.Final\netty-codec-socks-4.1.86.Final.jar;D:\r\io\netty\netty-codec-stomp\4.1.86.Final\netty-codec-stomp-4.1.86.Final.jar;D:\r\io\netty\netty-codec-xml\4.1.86.Final\netty-codec-xml-4.1.86.Final.jar;D:\r\io\netty\netty-common\4.1.86.Final\netty-common-4.1.86.Final.jar;D:\r\io\netty\netty-handler\4.1.86.Final\netty-handler-4.1.86.Final.jar;D:\r\io\netty\netty-transport-native-unix-common\4.1.86.Final\netty-transport-native-unix-common-4.1.86.Final.jar;D:\r\io\netty\netty-handler-proxy\4.1.86.Final\netty-handler-proxy-4.1.86.Final.jar;D:\r\io\netty\netty-handler-ssl-ocsp\4.1.86.Final\netty-handler-ssl-ocsp-4.1.86.Final.jar;D:\r\io\netty\netty-resolver\4.1.86.Final\netty-resolver-4.1.86.Final.jar;D:\r\io\netty\netty-resolver-dns\4.1.86.Final\netty-resolver-dns-4.1.86.Final.jar;D:\r\io\netty\netty-transport\4.1.86.Final\netty-transport-4.1.86.Final.jar;D:\r\io\netty\netty-transport-rxtx\4.1.86.Final\netty-transport-rxtx-4.1.86.Final.jar;D:\r\io\netty\netty-transport-sctp\4.1.86.Final\netty-transport-sctp-4.1.86.Final.jar;D:\r\io\netty\netty-transport-udt\4.1.86.Final\netty-transport-udt-4.1.86.Final.jar;D:\r\io\netty\netty-transport-classes-epoll\4.1.86.Final\netty-transport-classes-epoll-4.1.86.Final.jar;D:\r\io\netty\netty-transport-classes-kqueue\4.1.86.Final\netty-transport-classes-kqueue-4.1.86.Final.jar;D:\r\io\netty\netty-resolver-dns-classes-macos\4.1.86.Final\netty-resolver-dns-classes-macos-4.1.86.Final.jar;D:\r\io\netty\netty-transport-native-epoll\4.1.86.Final\netty-transport-native-epoll-4.1.86.Final-linux-x86_64.jar;D:\r\io\netty\netty-transport-native-epoll\4.1.86.Final\netty-transport-native-epoll-4.1.86.Final-linux-aarch_64.jar;D:\r\io\netty\netty-transport-native-kqueue\4.1.86.Final\netty-transport-native-kqueue-4.1.86.Final-osx-x86_64.jar;D:\r\io\netty\netty-transport-native-kqueue\4.1.86.Final\netty-transport-native-kqueue-4.1.86.Final-osx-aarch_64.jar;D:\r\io\netty\netty-resolver-dns-native-macos\4.1.86.Final\netty-resolver-dns-native-macos-4.1.86.Final-osx-x86_64.jar;D:\r\io\netty\netty-resolver-dns-native-macos\4.1.86.Final\netty-resolver-dns-native-macos-4.1.86.Final-osx-aarch_64.jar;D:\r\com\fasterxml\jackson\core\jackson-databind\2.13.0\jackson-databind-2.13.0.jar;D:\r\com\fasterxml\jackson\core\jackson-annotations\2.13.0\jackson-annotations-2.13.0.jar;D:\r\com\fasterxml\jackson\core\jackson-core\2.13.0\jackson-core-2.13.0.jar org.example.GreetServer 8月 25, 2025 5:29:14 下午 io.netty.channel.DefaultChannelPipeline onUnhandledInboundException 警告: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception. com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 0)): only regular white space (\r, \n, \t) is allowed between tokens at [Source: (String)"\u0000\u0000\u0000\u001E{"name":"Alice","greeting":""}"; line: 1, column: 2] at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:2391) at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:735) at com.fasterxml.jackson.core.base.ParserMinimalBase._throwInvalidSpace(ParserMinimalBase.java:713) at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._skipWSOrEnd(ReaderBasedJsonParser.java:2462) at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:698) at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:4762) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4668) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3630) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3598) at org.example.GreetServerHandler.channelRead0(GreetServerHandler.java:26) at org.example.GreetServerHandler.channelRead0(GreetServerHandler.java:15) at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:840)
最新发布
08-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值