3

ツイスト python を使用して、カスタム ポートで単純な SSH サーバーを作成しています。ここでport = reactor.listenTCP(_port, sshfactory)、_port はポートの整数を保持する変数です。port.loseConnection()コマンドとでサーバーをシャットダウンするときに、ポートを解放しますport.connectionLost(reason=None)。サーバーを起動して停止し、再度起動しようとすると、「ポート」オブジェクトには属性「ソケット」がありませんというタイトルのエラーが発生します

編集:完全なエラーメッセージ:

Unhandled error in Deferred:
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\twisted\internet\base.py", line 1175, in mainLoop
    self.runUntilCurrent()
  File "C:\Python27\lib\site-packages\twisted\internet\base.py", line 779, in runUntilCurrent
    call.func(*call.args, **call.kw)
  File "C:\Python27\lib\site-packages\twisted\internet\defer.py", line 238, in callback
    self._startRunCallbacks(result)
  File "C:\Python27\lib\site-packages\twisted\internet\defer.py", line 307, in _startRunCallbacks
    self._runCallbacks()
--- <exception caught here> ---
  File "C:\Python27\lib\site-packages\twisted\internet\defer.py", line 323, in _runCallbacks
    self.result = callback(self.result, *args, **kw)
  File "C:\Python27\lib\site-packages\twisted\internet\task.py", line 736, in <lambda>
    d.addCallback(lambda ignored: callable(*args, **kw))
  File "C:\Python27\lib\site-packages\twisted\internet\tcp.py", line 981, in connectionLost
    self._closeSocket()
  File "C:\Python27\lib\site-packages\twisted\internet\tcp.py", line 92, in _closeSocket
    skt = self.socket
exceptions.AttributeError: 'Port' object has no attribute 'socket'

Edit2: stopListening コードサンプル (Python 2.7):

stopListening sample.py

from twisted.cred import portal, checkers, credentials
from twisted.conch import error, avatar, recvline, interfaces as conchinterfaces
from twisted.conch.ssh import factory, userauth, connection, keys, session, common
from twisted.conch.insults import insults
from twisted.application import service, internet
from twisted.internet import reactor, protocol
from zope.interface import implements
import threading
import os

class SSHDemoProtocol(recvline.HistoricRecvLine):
    def __init__(self, user):
        self.user = user

    def connectionMade(self):
        recvline.HistoricRecvLine.connectionMade(self)
        self.showPrompt()

    def showPrompt(self):
        self.terminal.write("$ ")

class SSHDemoRealm:
    implements(portal.IRealm)
    def requestAvatar(self, avatarId, mind, *interfaces):
        if conchinterfaces.IConchUser in interfaces:
            return interfaces[0], SSHDemoAvatar(avatarId), lambda: None
        else:
            raise Exception("No supported interfaces found.")

def getRSAKeys():
    if not (os.path.exists('public.key') and os.path.exists('private.key')):
        # generate a RSA keypair
        print("Generating RSA keypair...")
        from Crypto.PublicKey import RSA
        KEY_LENGTH = 1024
        rsaKey = RSA.generate(KEY_LENGTH, common.entropy.get_bytes)
        publicKeyString = keys.makePublicKeyString(rsaKey)
        privateKeyString = keys.makePrivateKeyString(rsaKey)
        # save keys for next time
        file('public.key', 'w+b').write(publicKeyString)
        file('private.key', 'w+b').write(privateKeyString)
        print("done.")
    else:
        publicKeyString = file('public.key').read()
        privateKeyString = file('private.key').read()
    return publicKeyString, privateKeyString

def launchServer():
    _port = 4564
    password = 'password'
    sshFactory = factory.SSHFactory()
    sshFactory.portal = portal.Portal(SSHDemoRealm())
    users = {'user': password}
    sshFactory.portal.registerChecker(
        checkers.InMemoryUsernamePasswordDatabaseDontUse(**users))
    pubKeyString, privKeyString = getRSAKeys()
    sshFactory.publicKeys = {
        'ssh-rsa': keys.getPublicKeyString(data=pubKeyString)}
    sshFactory.privateKeys = {
        'ssh-rsa': keys.getPrivateKeyObject(data=privKeyString)}
    global port
    port = reactor.listenTCP(_port, sshFactory)
    reactor.addSystemEventTrigger('before', 'shutdown', stopServer)
    reactor.run(installSignalHandlers=False)

def startServer():
    thread = threading.Thread(target=launchServer)
    thread.start()

def stopServer():
    global port
    port.stopListening()
    reactor.stop()
    reactor.crash()

startServer()
stopServer()
startServer()

トレースバック:

>>> Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 505, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/home/paul/Desktop/Down2Home/stopListening sample.py", line 62, in launchServer
    port = reactor.listenTCP(_port, sshFactory)
  File "/usr/local/lib/python2.7/dist-packages/Twisted-9.0.0-py2.7-linux-x86_64.egg/twisted/internet/posixbase.py", line 355, in listenTCP
    p.startListening()
  File "/usr/local/lib/python2.7/dist-packages/Twisted-9.0.0-py2.7-linux-x86_64.egg/twisted/internet/tcp.py", line 855, in startListening
    raise CannotListenError, (self.interface, self.port, le)
CannotListenError: Couldn't listen on any:4564: [Errno 98] Address already in use.
4

2 に答える 2

0

解決策は、スレッドを完全に捨てて、組み込みの GUI とのインターフェース方法を使用することであることが判明しました。tksupport.install(root)Twisted はスレッドセーフではありません。

于 2013-06-13T05:03:36.683 に答える