#每个connector都有一个 Connection对象
@implementer(interfaces.ITCPTransport, interfaces.ISystemHandle) class Connection(_TLSConnectionMixin, abstract.FileDescriptor, _SocketCloser, _AbortingMixin): """ Superclass of all socket-based FileDescriptors. This is an abstract superclass of all objects which represent a TCP/IP connection based socket. @ivar logstr: prefix used when logging events related to this connection. @type logstr: C{str} """ def __init__(self, skt, protocol, reactor=None): abstract.FileDescriptor.__init__(self, reactor=reactor) self.socket = skt self.socket.setblocking(0) self.fileno = skt.fileno self.protocol = protocol def getHandle(self): """Return the socket for this connection.""" return self.socket 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)#recv读取数据 except socket.error as se: if se.args[0] == EWOULDBLOCK: return else: return main.CONNECTION_LOST return self._dataReceived(data)#调用内部方法 def _dataReceived(self, data): if not data: return main.CONNECTION_DONE rval = self.protocol.dataReceived(data)#调用-协议提供的数据接收方法 if rval is not None: offender = self.protocol.dataReceived warningFormat = ( 'Returning a value other than None from %(fqpn)s is ' 'deprecated since %(version)s.') warningString = deprecate.getDeprecationWarningString( offender, versions.Version('Twisted', 11, 0, 0), format=warningFormat) deprecate.warnAboutFunction(offender, warningString) return rval def writeSomeData(self, data): """ Write as much as possible of the given data to this TCP connection. This sends up to C{self.SEND_LIMIT} bytes from C{data}. If the connection is lost, an exception is returned. Otherwise, the number of bytes successfully written is returned. """ # Limit length of buffer to try to send, because some OSes are too # stupid to do so themselves (ahem windows) limitedData = lazyByteSlice(data, 0, self.SEND_LIMIT) try: return untilConcludes(self.socket.send, limitedData) except socket.error as se: if se.args[0] in (EWOULDBLOCK, ENOBUFS): return 0 else: return main.CONNECTION_LOST def _closeWriteConnection(self): try: self.socket.shutdown(1) except socket.error: pass p = interfaces.IHalfCloseableProtocol(self.protocol, None) if p: try: p.writeConnectionLost() except: f = failure.Failure() log.err() self.connectionLost(f) def readConnectionLost(self, reason): p = interfaces.IHalfCloseableProtocol(self.protocol, None) if p: try: p.readConnectionLost() except: log.err() self.connectionLost(failure.Failure()) else: self.connectionLost(reason) def connectionLost(self, reason): """See abstract.FileDescriptor.connectionLost(). """ # Make sure we're not called twice, which can happen e.g. if # abortConnection() is called from protocol's dataReceived and then # code immediately after throws an exception that reaches the # reactor. We can't rely on "disconnected" attribute for this check # since twisted.internet._oldtls does evil things to it: if not hasattr(self, "socket"): return abstract.FileDescriptor.connectionLost(self, reason) self._closeSocket(not reason.check(error.ConnectionAborted)) protocol = self.protocol del self.protocol del self.socket del self.fileno protocol.connectionLost(reason) logstr = "Uninitialized" def logPrefix(self): """Return the prefix to log with when I own the logging thread. """ return self.logstr def getTcpNoDelay(self): return operator.truth(self.socket.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY)) def setTcpNoDelay(self, enabled): self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, enabled) def getTcpKeepAlive(self): return operator.truth(self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE)) def setTcpKeepAlive(self, enabled): self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, enabled)