观看上章的代码, reactor似乎没有主动加入过 reader/writer, reactor如何操作socket的呢?
重新想象reactor在run之前还做过什么?
对了, 连接/建立连接!
就如reactor.listenTCP
def listenTCP(self, port, factory, backlog=50, interface=''):
p = tcp.Port(port, factory, backlog, interface, self)
p.startListening()
return p
看看tcp.Port的设计
tcp.Port继承于base.BasePort 和 tcp._SocketCloser,
而base.BasePort 继承于abstract.FileDescriptor, 一个抽象的文件操作符类
tcp.Port实例化时没有做太多动作, 我们聚焦在方法 startListening 上
# tcp.Port.startListening 生成并绑定了一个socket
# 也没有做什么过多的动作, 直接看看最下面的startReading
def startListening(self):
try:
skt = self.createInternetSocket()
skt.bind((self.interface, self.port))
except socket.error, le:
raise CannotListenError, (self.interface, self.port, le)
# Make sure that if we listened on port 0, we update that to
# reflect what the OS actually assigned us.
self._realPortNumber = skt.getsockname()[1]
log.msg("%s starting on %s" % (self.factory.__class__, self._realPortNumber))
# The order of the next 6 lines is kind of bizarre. If no one
# can explain it, perhaps we should re-arrange them.
self.factory.doStart()
skt.listen(self.backlog)
self.connected = True
self.socket = skt
self.fileno = self.socket.fileno
self.numberAccepts = 100
self.startReading()
# 一直找到abstract.FileDescriptor.startReading
# 执行了reactor.addReader
def startReading(self):
"""Start waiting for read availability.
"""
self.reactor.addReader(self)
# selectreactor.SelectReactor.addReader指明了
# 一个tcp.Port对象被作为reader加入到了reactor的reads队列中
def addReader(self, reader):
"""
Add a FileDescriptor for notification of data available to read.
"""
self._reads[reader] = 1
原来在这里, 在reactor.listenTCP时候就被加入到了reader队列中.
赶紧回头看看, 在 selectreactor.SelectReactor.doSelect中,如果一个类文件操作符状态改变了,会执行其doRead/doWriter方法.那去看看作为reader的tcp.Port的doRead方法.
# tcp.Port的socket接受了一个连接,
# 并执行了self.factory.buildProtocol方法生成一个portocol
# 通过self.transport生成了一个tcp.Server对象
def doRead(self):
try:
if platformType == "posix":
numAccepts = self.numberAccepts
else:
# win32 event loop breaks if we do more than one accept()
# in an iteration of the event loop.
numAccepts = 1
for i in range(numAccepts):
# we need this so we can deal with a factory's buildProtocol
# calling our loseConnection
if self.disconnecting:
return
try:
skt, addr = self.socket.accept()
except socket.error, e:
if e.args[0] in (EWOULDBLOCK, EAGAIN):
self.numberAccepts = i
break
elif e.args[0] == EPERM:
# Netfilter on Linux may have rejected the
# connection, but we get told to try to accept()
# anyway.
continue
elif e.args[0] in (EMFILE, ENOBUFS, ENFILE, ENOMEM, ECONNABORTED):
log.msg("Could not accept new connection (%s)" % (
errorcode[e.args[0]],))
break
raise
protocol = self.factory.buildProtocol(self._buildAddr(addr))
if protocol is None:
skt.close()
continue
s = self.sessionno
self.sessionno = s+1
transport = self.transport(skt, protocol, addr, self, s, self.reactor)
transport = self._preMakeConnection(transport)
protocol.makeConnection(transport)
else:
self.numberAccepts = self.numberAccepts+20
except:
log.deferr()
虽然还有点迷糊, 不过知道了protocol对象产生于此处.那这个产生的transport实例具体作用是什么呢?
先看下 protocol.makeConnection
# protocol.BaseProtocol
def makeConnection(self, transport):
self.connected = 1
self.transport = transport
self.connectionMade()
看到了一个熟悉的方法connectionMade!
protocol的三个事件方法 connectionMade, dataReceived, connectionLost是protocol最重要的三个方法了.
其一出现了, 剩下的两个是在何处被触发的呢?
先不急, 先看看transport 是怎么回事:
tcp.Server 来自于 父类 tcp.Connection. 而Connection继承于abstract.FileDescriptor,又是一个类文件符.
tcp.Server实例时还是做了点小动作的
# tcp.Server
def __init__(self, sock, protocol, client, server, sessionno, reactor):
Connection.__init__(self, sock, protocol, reactor)
self.server = server
self.client = client
self.sessionno = sessionno
self.hostname = client[0]
self.logstr = "%s,%s,%s" % (self.protocol.__class__.__name__,
sessionno,
self.hostname)
self.repstr = "<%s #%s on %s>" % (self.protocol.__class__.__name__,
self.sessionno,
self.server._realPortNumber)
self.startReading()
self.connected = 1
self.startReading从 abstract.FileDescriptor上知晓是把 该实例作为reader加入到reactor队列中的.
那我们就看看tcp.Server的doRead方法
# tcp.Connection
def doRead(self):
"""Calls self.protocol.dataReceived with all available data.
This reads up to self.bufferSize bytes of data from its socket, then
calls self.dataReceived(data) to process it. If the connection is not
lost through an error in the physical recv(), this function will return
the result of the dataReceived call.
"""
try:
data = self.socket.recv(self.bufferSize)
except socket.error, se:
if se.args[0] == EWOULDBLOCK:
return
else:
return main.CONNECTION_LOST
if not data:
return main.CONNECTION_DONE
return self.protocol.dataReceived(data)
眼前一亮, dataReceived方法!
分享到:
相关推荐
赠送jar包:reactor-core-3.4.10.jar; 赠送原API文档:reactor-core-3.4.10-javadoc.jar; 赠送源代码:reactor-core-3.4.10-sources.jar; 赠送Maven依赖信息文件:reactor-core-3.4.10.pom; 包含翻译后的API文档...
赠送jar包:reactor-core-3.4.14.jar; 赠送原API文档:reactor-core-3.4.14-javadoc.jar; 赠送源代码:reactor-core-3.4.14-sources.jar; 赠送Maven依赖信息文件:reactor-core-3.4.14.pom; 包含翻译后的API文档...
2) 运行安装程序:dotnet_reactor_setup_4_9_0_0.exe(也可在官网下载安装,下载地址:http://www.eziriz.com/downloads/dotnet_reactor_setup_4_9_0_0.exe). 3) 使用Crack文件夹下的破解版替换安装目录下的"dotNET_...
赠送jar包:reactor-extra-3.4.5.jar; 赠送原API文档:reactor-extra-3.4.5-javadoc.jar; 赠送源代码:reactor-extra-3.4.5-sources.jar; 赠送Maven依赖信息文件:reactor-extra-3.4.5.pom; 包含翻译后的API文档...
赠送jar包:reactor-netty-core-1.0.15.jar; 赠送原API文档:reactor-netty-core-1.0.15-javadoc.jar; 赠送源代码:reactor-netty-core-1.0.15-sources.jar; 赠送Maven依赖信息文件:reactor-netty-core-1.0.15....
.NET Reactor是一款功能强大的代码保护以及许可授权管理系统软件,主要用于开发人员保护其.NET软件程序,.NET Reactor支持所有支持.NET编译的程序开发语言。控件中国网是.NET Reactor在中国正式的授权销售商,提供...
赠送jar包:reactor-netty-http-1.0.11.jar; 赠送原API文档:reactor-netty-http-1.0.11-javadoc.jar; 赠送源代码:reactor-netty-http-1.0.11-sources.jar; 赠送Maven依赖信息文件:reactor-netty-...
赠送jar包:reactor-extra-3.4.6.jar; 赠送原API文档:reactor-extra-3.4.6-javadoc.jar; 赠送源代码:reactor-extra-3.4.6-sources.jar; 赠送Maven依赖信息文件:reactor-extra-3.4.6.pom; 包含翻译后的API文档...
NET+Reactor_1279带破解文件NET+Reactor_1279带破解文件NET+Reactor_1279带破解文件NET+Reactor_1279带破解文件
Reactor教程Mono和Flux例子,同时可以查看我的博客,有介绍如何使用Reactor的详细教程
java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现Reactor模型源码java基于NIO实现...
NET REACTOR中文手册
Reactor3中文帮助文档,帮助初学者了解非阻塞响应式式框架的使用以及原理,帮助了解spring webflux的一些底层实现原理
.NET Reactor V4.5代码保护(防反编译) 与模糊工具(Obfuscator)相比,.NET Reactor 可以完全阻止对 .NET 程序集(由 C#, VB.NET, Delphi.NET, J#, MSIL... 等语言编写)的反编译。通俗的讲,.NET Reactor 在破解者...
Reactor 是一个基于 JVM 之上的异步应用基础库。为 Java 、Groovy 和其他 JVM 语言提供了构建基于事件和数据驱动应用的抽象库。Reactor 性能相当高,在最新的硬件平台上,使用无堵塞分发器每秒钟可处理 1500 万事件...
.NET Reactor是一款项目知识产权保护软件。它能够使你的程序无法反编译,它可以为你程序生成一套许可证系统。
netty 入门Reactor示例
spring reactor 编译包 https://github.com/reactor/reactor
Reactor 3参考文档,reactor 3是一个围绕Reactive Streams规范构建的库,它在JVM上引入了响应式编程的一个范例。目前Spring5 引入的Webflux就是reactor 3实现的一个响应式web框架
.net reactor 6.3免费版