当前位置: 首页 > 面试题库 >

扭曲的海螺文件传输

裴泰平
2023-03-14
问题内容

我正在尝试使用扭曲的海螺在python中实现一个非常简单的文件传输客户端。客户端应该简单地以编程方式将一些文件传输到远程ssh /
sftp服务器。该功能提供了用户名,密码,文件列表,目标服务器:目录,只需要以跨平台的方式进行身份验证和复制。

我已经阅读了有关Twisted的一些入门资料,并设法制作了自己的SSH客户端,该客户端仅cat在远程服务器上执行。我很难将其扩展到移动文件。我看了cftp.py和文件传输测试,但完全被扭曲弄得迷惑不解。

有没有人能给我正确的方向的建议或参考?我已经构建的SSH客户端就是基于这个客户端的。


问题答案:

使用Twisted
Conch进行SFTP文件传输涉及两个不同的阶段(嗯,如果斜视,它们是不同的)。基本上,首先,您需要建立一个连接,并在其上打开一个通道,并在其上运行sftp子系统。ew。然后,您可以使用连接到该通道的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并覆盖其getPasswordgetPublicKeygetPrivateKey,和/或signData方法,或者你可以写有你想要的任何其他身份验证逻辑自己完全不同的类。查看实现,以查看SSH协议实现调用哪种方法来完成身份验证。

因此,此功能将建立SSH连接并进行身份验证。完成之后,SFTPConnection实例开始起作用。注意如何SSHUserAuthClientSFTPConnection实例作为参数。身份验证成功后,它将移交对该实例连接的控制。特别是,该实例已对其进行了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我设置为insftpFileTransferClient连接被解雇了_cbSFTP。然后sftpget的调用者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在创建目录时触发(或在执行此操作时发生错误)时触发的。传输文件要复杂得多,因为您必须提供要发送的数据,或者定义在下载而不是上传时如何解释接收到的数据。

但是,如果您阅读docstring的方法FileTransferClient,则应该了解如何使用其其他功能-
对于实际文件传输,openFile主要是感兴趣的。它为您Deferred提供了一个使用ISFTPFile提供程序触发的功能。该对象具有读取和写入文件内容的方法。



 类似资料:
  • 问题内容: 什么是Twisted最接近的Java替代方案? 问题答案: 与斯蒂芬(Stephane)一样,我建议您看一下Mina。它是异步网络IO的框架。它建立在前面提到的NIO之上,并且IMO隐藏了与Selectors,Channels等有关的一些复杂性。我已经使用Mina进行了几个项目,其效果相当不错,但是请注意,我发现文档有些薄弱。再有,就像Stephane提到的那样,它并没有对太多协议的现

  • 问题内容: 谁能推荐一些简单的代码来使用Twisted设置简单的JSON RPC客户端和服务器? 我找到了txJSON-RPC,但我想知道是否有人对使用这些anc有一定的经验可以推荐一些东西。 问题答案: txJSONRPC很棒。我使用它,并且有效。我建议您尝试一下。 客户: 作为奖励,我将保留一些替代方案:放大器。 http://amp-protocol.net

  • 嗨,我想使用鱼眼失真插件为我的力定向图在d3。但当我想应用这个插件时,graph的行为很奇怪。我是d3新手。而且不擅长计算机图形学。 在jsfiddle中完成示例 奇怪的行为我的意思是图的节点在鼠标悬停后消失(隐藏)。

  • 问题内容: websockets有趣的部分是从服务器向浏览器发送本质上未经请求的内容,对吗? 好吧,我正在使用GregorMüllegger的django-websocket。使Websockets在Django中工作确实是一个很棒的早期尝试。 我完成了“ helloworld”。它的工作方式是:当请求是websocket时,会将对象websocket附加到请求对象。因此,在解释websocket

  • 我想像这样扭曲图像: 2013年4月8日新增:我使用了此代码,但无法正常工作:

  • 问题内容: 我正在尝试开始学习如何创建套接字服务器。我想添加一些有用的功能(例如auth,也许还有其他一些功能)。也许有人可以给我指出一个很好的教程,这将帮助我入门(+也许还有其他一些想法) 问题答案: 看这里:60秒内扭曲的网。这是一组博客文章,逐步描述了如何使用Twisted做很多常见的事情,所有这些都是由Twisted的最大贡献者Jean- Paul Calderone撰写的。这确实是您应该