扭曲海螺文件传输
回答
用扭曲海螺进行SFTP文件传输涉及到几个不同的阶段(当然,如果你斜视它们,它们是不同的)。基本上,首先你需要建立一个连接,并在其上打开一个通道,并在其上运行一个sftp子系统。呼。然后,您可以使用连接到该通道的FileTransferClient实例的方法来执行要执行的任何SFTP操作。
通过twisted.conch.client包中的模块提供的API可以为您设置获取SSH连接的最基本要求。下面是在一个稍微不那么令人惊讶的接口包扎的twisted.conch.client.default.connect
轻微古怪的函数:
from twisted.internet.defer import Deferred
from twisted.conch.scripts.cftp import ClientOptions
from twisted.conch.client.connect import connect
from twisted.conch.client.default import SSHUserAuthClient, verifyHostKey
def sftp(user, host, port):
options = ClientOptions()
options['host'] = host
options['port'] = port
conn = SFTPConnection()
conn._sftp = Deferred()
auth = SSHUserAuthClient(user, options, conn)
connect(host, port, options, verifyHostKey, auth)
return conn._sftp
此功能需要一个用户名,主机名(或IP地址)和端口号,并设置了一个经过验证的SSH连接服务器在该地址使用与给定用户名关联的帐户。
实际上,它做的比这更多一点,因为SFTP设置在这里有点混杂。尽管如此,忽略SFTPConnection
和_sftp
推迟。
ClientOptions
基本上只是一个奇特的字典,connect
希望能够看到它连接到什么,所以它可以验证主机密钥。
SSHUserAuthClient
是定义如何进行身份验证的对象。这个班级知道如何尝试通常的事情,比如查看~/.ssh
并与本地SSH代理交谈。如果你想改变身份验证的方式,这是一个可以玩的对象。你也可以继承SSHUserAuthClient
并覆盖其getPassword
,getPublicKey
,getPrivateKey
,和/或signData
方法,或者你可以写有你想要的任何其他身份验证逻辑自己完全不同的类。看一下实现,看看SSH协议实现调用什么方法来完成身份验证。
所以这个功能将建立一个SSH连接和验证它。完成之后,SFTPConnection
实例即可发挥作用。请注意0如何将SFTPConnection
实例作为参数。一旦验证成功,它将切断对该实例的连接控制。特别是,该实例已调用serviceStarted
。下面是完整的实施SFTPConnection
类:
class SFTPConnection(SSHConnection):
def serviceStarted(self):
self.openChannel(SFTPSession())
很简单:它是所有开放的新渠道。它通过的SFTPSession
实例可以与该新通道进行交互。我是这样定义的SFTPSession
:
class SFTPSession(SSHChannel):
name = 'session'
def channelOpen(self, whatever):
d = self.conn.sendRequest(
self, 'subsystem', NS('sftp'), wantReply=True)
d.addCallbacks(self._cbSFTP)
def _cbSFTP(self, result):
client = FileTransferClient()
client.makeConnection(self)
self.dataReceived = client.dataReceived
self.conn._sftp.callback(client)
像与SFTPConnection
,这个类有一个当连接已经准备好了被调用方法。在这种情况下,当通道成功打开时调用它,方法是channelOpen
。
最后,启动SFTP子系统的要求已到位。因此,channelOpen
通过频道发送请求以启动该子系统。它要求回复,以便它可以知道何时成功(或失败)。它为Deferred
添加了一个回调函数,它将FileTransferClient
连接到自身。
FileTransferClient
实例将实际上格式化和解析通过此连接通道移动的字节。换句话说,它是一个执行只是的SFTP协议。它运行在SSH协议上,这个例子创建了其他对象。但就其而言,它在其dataReceived
方法中接收字节,解析它们并将数据分派给回调函数,并提供接受结构化Python对象,将这些对象格式化为正确字节并将它们写入其传输的方法。
尽管如此,这对于使用它并不重要。但是,在举例说明如何执行SFTP操作之前,我们先介绍一下_sftp
属性。这是我粗略的方法,使这个新连接的FileTransferClient
实例可用于其他代码,它实际上会知道如何处理它。将SFTP设置代码从实际使用SFTP连接的代码中分离出来,更容易在重新使用前者的同时更改后者。
所以Deferred
我设置在sftp
被解雇了FileTransferClient
连接_cbSFTP
。和sftp
调用者得到了Deferred
归还给他们,因此代码可以做这样的事情:
def transfer(client):
d = client.makeDirectory('foobarbaz', {})
def cbDir(ignored):
print 'Made directory'
d.addCallback(cbDir)
return d
def main():
...
d = sftp(user, host, port)
d.addCallback(transfer)
所以第一sftp
建立全连接,一路向上连接本地FileTransferClient
实例字节流在另一端具有一些SSH服务器的SFTP子系统,然后transfer
接受该实例并使用它创建一个目录,使用FileTransferClient
中的一种方法执行某些SFTP操作。
下面是一个完整的代码清单,你应该能够运行,并看到一些SFTP服务器上创建一个目录:
from sys import stdout
from twisted.python.log import startLogging, err
from twisted.internet import reactor
from twisted.internet.defer import Deferred
from twisted.conch.ssh.common import NS
from twisted.conch.scripts.cftp import ClientOptions
from twisted.conch.ssh.filetransfer import FileTransferClient
from twisted.conch.client.connect import connect
from twisted.conch.client.default import SSHUserAuthClient, verifyHostKey
from twisted.conch.ssh.connection import SSHConnection
from twisted.conch.ssh.channel import SSHChannel
class SFTPSession(SSHChannel):
name = 'session'
def channelOpen(self, whatever):
d = self.conn.sendRequest(
self, 'subsystem', NS('sftp'), wantReply=True)
d.addCallbacks(self._cbSFTP)
def _cbSFTP(self, result):
client = FileTransferClient()
client.makeConnection(self)
self.dataReceived = client.dataReceived
self.conn._sftp.callback(client)
class SFTPConnection(SSHConnection):
def serviceStarted(self):
self.openChannel(SFTPSession())
def sftp(user, host, port):
options = ClientOptions()
options['host'] = host
options['port'] = port
conn = SFTPConnection()
conn._sftp = Deferred()
auth = SSHUserAuthClient(user, options, conn)
connect(host, port, options, verifyHostKey, auth)
return conn._sftp
def transfer(client):
d = client.makeDirectory('foobarbaz', {})
def cbDir(ignored):
print 'Made directory'
d.addCallback(cbDir)
return d
def main():
startLogging(stdout)
user = 'exarkun'
host = 'localhost'
port = 22
d = sftp(user, host, port)
d.addCallback(transfer)
d.addErrback(err, "Problem with SFTP transfer")
d.addCallback(lambda ignored: reactor.stop())
reactor.run()
if __name__ == '__main__':
main()
makeDirectory
是一个相当简单的操作。 makeDirectory
方法返回一个Deferred
,该目录在创建目录时触发(或者如果发生错误)。传输文件有一点涉及,因为您必须提供要发送的数据,或者定义在下载而不是上传时如何解释接收的数据。
如果您阅读FileTransferClient
方法的文档字符串,您应该看看如何使用其他功能 - 对于实际的文件传输,openFile
主要是感兴趣的。它会为您提供一个Deferred
,它会与ISFTPFile供应商一起启动。该对象具有读写文件内容的方法。
- 1. Python的扭曲:扭曲海螺文件传输verifyHostKey
- 2. 扭曲的海螺,重写身份验证
- 3. Python扭曲的海螺 - 如何停止与多个连接的反应堆?
- 4. 扭曲的大文件和字符串传输
- 5. 扭曲和扭曲Movieclip
- 6. 的Java文件复制扭曲文件
- 7. 扭曲,FTP和“流”大文件
- 8. 扭曲 - 发送文件层次结构
- 9. 用扭曲的方式监视文件
- 10. IE中的文本扭曲
- 11. Python的扭曲文档
- 12. QTextEdit中的文本扭曲
- 13. 验证控件扭曲UI
- 14. CATiledlayer扭曲CGPath
- 15. 学习扭曲
- 16. 在扭曲
- 17. JTable autoresize,扭曲?
- 18. 扭曲在https
- 19. python3.5扭曲?
- 20. 使用扭曲
- 21. 图像在上传时被扭曲
- 22. 扭曲:如何隐式传递参数?
- 23. glDrawArrays将输出扭曲到CCRenderTexture
- 24. 缩放位图输出扭曲图像
- 25. 扭曲self.transport.write() - Python的 - 追加输出
- 26. 扭曲 - 传递协议(和套接字句柄)对象扭子
- 27. UISlider扭曲圆角
- 28. 扭曲XML格式
- 29. Google App Engine扭曲
- 30. 扭曲的错误
你能解释一下你是如何陷入更具体的吗?现在你的问题是,我能想到的唯一方法就是编写一个完整的海螺/ SFTP教程,这对于SO来说可能比15分更有用(至少目前是这样)。 ;)但更具体的问题可能有一个更简单的答案。 – 2011-03-04 16:17:10
@让 - 保罗现在我_think_我需要继承t.c.s.f.FileTransferClient。我还想_我需要打开一个类似于上面链接的示例的SSH连接。我坚持如何正确地继承t.c.s.f.FileTransferClient的子类以及如何实际移动文件。完整的教程并不是必要的,因为我有兴趣学习扭曲(这是我的第一个小项目),但是我应该使用或阅读哪些方法和类的草图,甚至是文档中的简单例子(我发现cftp.py难以阅读)将不胜感激。 – rymurr 2011-03-04 16:50:34