Python 关闭Twisted conch SSH连接的正确方法是什么?

Python 关闭Twisted conch SSH连接的正确方法是什么?,python,twisted,twisted.conch,Python,Twisted,Twisted.conch,关闭Twisted conch SSH连接的正确方法是什么?有没有明确的方法可以做到这一点 我看到的所有扭曲海螺示例都关闭SSH通道,然后停止反应堆。反应堆停堆似乎意味着要关闭连接。但是,我正在将wxreactor与wxPython一起使用,我不想停止该反应器,但我想在使用完它后关闭ssh连接 在查看了t.c.s.connection之后,似乎serviceStopped()方法就是最好的选择。它关闭所有打开的通道,并在完成时运行_cleanupGlobalDeferreds(),但随后我开始出

关闭Twisted conch SSH连接的正确方法是什么?有没有明确的方法可以做到这一点

我看到的所有扭曲海螺示例都关闭SSH通道,然后停止反应堆。反应堆停堆似乎意味着要关闭连接。但是,我正在将wxreactor与wxPython一起使用,我不想停止该反应器,但我想在使用完它后关闭ssh连接

在查看了t.c.s.connection之后,似乎serviceStopped()方法就是最好的选择。它关闭所有打开的通道,并在完成时运行_cleanupGlobalDeferreds(),但随后我开始出现如下异常:

Unhandled Error
Traceback (most recent call last):
  File "C:\Users\me\venv\lib\site-packages\twisted\internet\tcp.py", line 203, in doRead
    return self._dataReceived(data)
  File "C:\Users\me\venv\lib\site-packages\twisted\internet\tcp.py", line 209, in _dataReceived
    rval = self.protocol.dataReceived(data)
  File "C:\Users\me\venv\lib\site-packages\twisted\conch\ssh\transport.py", line 438, in dataReceived
    self.dispatchMessage(messageNum, packet[1:])
  File "C:\Users\me\venv\lib\site-packages\twisted\conch\ssh\transport.py", line 460, in dispatchMessage
    messageNum, payload)
--- <exception caught here> ---
  File "C:\Users\me\venv\lib\site-packages\twisted\python\log.py", line 84, in callWithLogger
    return callWithContext({"system": lp}, func, *args, **kw)
  File "C:\Users\me\venv\lib\site-packages\twisted\python\log.py", line 69, in callWithContext
    return context.call({ILogContext: newCtx}, func, *args, **kw)
  File "C:\Users\me\venv\lib\site-packages\twisted\python\context.py", line 118, in callWithContext
    return self.currentContext().callWithContext(ctx, func, *args, **kw)
  File "C:\Users\me\venv\lib\site-packages\twisted\python\context.py", line 81, in callWithContext
    return func(*args,**kw)
  File "C:\Users\me\venv\lib\site-packages\twisted\conch\ssh\service.py", line 44, in packetReceived
    return f(packet)
  File "C:\Users\me\venv\lib\site-packages\twisted\conch\ssh\connection.py", line 228, in ssh_CHANNEL_DATA
    channel = self.channels[localChannel]
exceptions.KeyError: 0
调用此方法时,self.factory.d似乎始终为None,因此它返回时不调用t.c.s.t.SSHClientTransport.sendDisconnect()。我认为它最初是t.c.c.d.connect中的一个延迟集,但在某个点上它被设置为“无”

我怀疑SSHClientTransport.loseConnection()是关闭SSH连接的正确方法,但是为什么当twisted希望self.factory.d是其他连接时,self.factory.d设置为None呢


如果loseConnection()不是关闭SSH连接的正确方法,有人能给我指出正确的方向吗?

听起来你在使用
twisted.conch.client.direct.SSHClientFactory
twisted.conch.client.direct.SSHClientTransport
。这些类最直接地用于实现
conch
命令行工具。这意味着它们对于构建SSH客户机非常有用,因为这正是
conch
的含义

然而,它们也没有人们想象的那么有用,因为除了实现
conch
命令行工具之外,它们不太注意做任何“其他”事情


更普遍适用的SSH客户端传输类是
twisted.conch.SSH.transport.SSHClientTransport
。这个类没有任何额外的逻辑来实现
conch
命令行工具的某些特定行为。它只有SSH客户端逻辑。例如,它没有一个无法解释的
self.factory.d
内部检查
sendDisconnect
-它的
sendDisconnect
实现只是发送一个断开数据包,然后关闭连接。

我遇到了同样的问题。我确信这是一个bug,
sendDisconnect()
不调用父实现。在
SSHClientTransport
上调用
loseConnection()
不会为我关闭TCP连接,我可以使用
lsof-p PID
看到这一点。为了解决这个问题,我使用自己的
connect()
方法注入自己的
SSHClientTransport
实现。以下代码修复了该问题:

class SSHClientTransport(direct.SSHClientTransport):
    '''
    Orignal sendDisconnect() is bugged.
    '''

    def sendDisconnect(self, code, reason):
        d, self.factory.d = self.factory.d, None
        # call the sendDisconnect() on the base SSHTransport,
        # not the imediate parent class
        transport.SSHClientTransport.sendDisconnect(self, code, reason)
        if d:
            d.errback(error.ConchError(reason, code))
def sendDisconnect(self, code, reason):
    if self.factory.d is None:
        return
    d, self.factory.d = self.factory.d, None
    transport.SSHClientTransport.sendDisconnect(self, code, reason)
    d.errback(error.ConchError(reason, code))
class SSHClientTransport(direct.SSHClientTransport):
    '''
    Orignal sendDisconnect() is bugged.
    '''

    def sendDisconnect(self, code, reason):
        d, self.factory.d = self.factory.d, None
        # call the sendDisconnect() on the base SSHTransport,
        # not the imediate parent class
        transport.SSHClientTransport.sendDisconnect(self, code, reason)
        if d:
            d.errback(error.ConchError(reason, code))