我正在继承ReconnectingClientFactory
并使用SSL连接。我们所有的运行都在运行,但是几分钟后我会遇到以下错误。一旦发生此错误,连接就会丢失
Unhandled Error
Traceback (most recent call last):
File "/usr/local/hikvision/ezops/python/lib/python2.7/site-packages/twisted/python/log.py", line 103, in callWithLogger
return callWithContext({"system": lp}, func, *args, **kw)
File "/usr/local/hikvision/ezops/python/lib/python2.7/site-packages/twisted/python/log.py", line 86, in callWithContext
return context.call({ILogContext: newCtx}, func, *args, **kw)
File "/usr/local/hikvision/ezops/python/lib/python2.7/site-packages/twisted/python/context.py", line 118, in callWithContext
return self.currentContext().callWithContext(ctx, func, *args, **kw)
File "/usr/local/hikvision/ezops/python/lib/python2.7/site-packages/twisted/python/context.py", line 81, in callWithContext
return func(*args,**kw)
--- <exception caught here> ---
File "/usr/local/hikvision/ezops/python/lib/python2.7/site-packages/twisted/internet/posixbase.py", line 597, in _doReadOrWrite
why = selectable.doRead()
File "/usr/local/hikvision/ezops/python/lib/python2.7/site-packages/twisted/internet/tcp.py", line 208, in doRead
return self._dataReceived(data)
File "/usr/local/hikvision/ezops/python/lib/python2.7/site-packages/twisted/internet/tcp.py", line 214, in _dataReceived
rval = self.protocol.dataReceived(data)
File "/usr/local/hikvision/ezops/python/lib/python2.7/site-packages/twisted/protocols/tls.py", line 430, in dataReceived
self._flushReceiveBIO()
File "/usr/local/hikvision/ezops/python/lib/python2.7/site-packages/twisted/protocols/tls.py", line 400, in _flushReceiveBIO
self._flushSendBIO()
File "/usr/local/hikvision/ezops/python/lib/python2.7/site-packages/twisted/protocols/tls.py", line 352, in _flushSendBIO
bytes = self._tlsConnection.bio_read(2 ** 15)
File "/usr/local/hikvision/ezops/python/lib/python2.7/site-packages/OpenSSL/SSL.py", line 1384, in bio_read
self._handle_bio_errors(self._from_ssl, result)
File "/usr/local/hikvision/ezops/python/lib/python2.7/site-packages/OpenSSL/SSL.py", line 1365, in _handle_bio_errors
_raise_current_error()
File "/usr/local/hikvision/ezops/python/lib/python2.7/site-packages/OpenSSL/_util.py", line 48, in exception_from_error_queue
raise exception_type(errors)
OpenSSL.SSL.Error: []
我的客户端代码:
reactor.connectSSL(opscenter_addr, int(opscenter_port), NoahAgentFactory(), ssl.ClientContextFactory())
类似这样的类NoahagentFactory:
import logging
import traceback
from OpenSSL import SSL
from twisted.internet import reactor,ssl
from twisted.internet import task
from twisted.internet.protocol import Protocol
from twisted.internet.protocol import ReconnectingClientFactory
import DataPackageCodecFactory as Codec
from Header import MessageHandlerMap
from Handler import HBReq, DefaultRspHandler
from Util import Connection
logger = logging.getLogger('opsagent')
class NoahAgentProtocol(Protocol):
t = None
def connectionMade(self):
'''
客户端连接成功之后会自动调用该方法
:return:
'''
self.transport.setTcpKeepAlive(True) # maintain the TCP connection
self.transport.setTcpNoDelay(True) # allow Nagle algorithm
# 连接成功后保存连接信息
Connection.AgentTcpConnection = self
global t
logger.info('is already connect to the server')
self.recv_data_buffer = ''
# 创建定时的心跳任务,每隔30秒执行一次
t = task.LoopingCall(HBReq.execute, *[self])
t.start(30)
def dataReceived(self, data):
logger.debug("Received Message: %s", repr(data))
###code handler packages##########
def connectionLost(self, reason):
'''
当客户端连接断开的时候,会自动调用该方法
:param reason:
:return:
'''
try:
t.stop()
# 清空全局链接信息
Connection.AgentTcpConnection = None
except:
logger.error(traceback.format_exc())
logger.info('Connection is lost and Task stopped,Resaon =>%s', reason)
class NoahAgentFactory(ReconnectingClientFactory):
def startedConnecting(self, connector):
logger.info('Started to connect.')
def buildProtocol(self, addr):
logger.info('Connected.')
logger.info('Resetting reconnection delay')
self.resetDelay()
return NoahAgentProtocol()
def clientConnectionLost(self, connector, reason):
logger.info('Lost connection. Reason:%s', reason)
self.resetDelay()
self.retry(connector)
# ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
def clientConnectionFailed(self, connector, reason):
logger.info('Connection failed. Reason:%s', reason)
self.resetDelay()
self.retry(connector)
我认为这不是扭曲的tls中的错误,而不是错误,我将消息发送给不是主反应堆线程中,众所周知,扭曲是单线程模式,所以有无需考虑线程安全问题。但是我使用反应器。callinthread来处理长时间的成本量并直接发送消息,而写入()不是线程安全,所以调用该错误,一旦我使用反应器。它在正确运行。