扭曲海螺文件傳輸
回答
用扭曲海螺進行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. 扭曲的大文件傳輸
- 4. 扭曲的海螺數據包完整性錯誤
- 5. 扭曲的海螺,重寫身份驗證
- 6. 使用扭曲海螺的ISFTP接口來執行下載和上傳?
- 7. 扭海螺 - 服務器/客戶端
- 8. Python扭曲的海螺 - 如何停止與多個連接的反應堆?
- 9. 扭曲的大文件和字符串傳輸
- 10. 讀取文件,扭曲
- 11. FileSystemWatcher扭曲文件名
- 12. 扭曲和扭曲Movieclip
- 13. 錯誤而通過ssh與扭海螺連接
- 14. 的Java文件複製扭曲文件
- 15. 無法獲取扭曲的上傳文件
- 16. 電子郵件正文中的輸出格式扭曲
- 17. 用扭曲的方式監視文件
- 18. 扭曲,FTP和「流」大文件
- 19. 扭曲 - 發送文件層次結構
- 20. 如何加密扭曲的文件?
- 21. Python的扭曲文檔
- 22. QTextEdit中的文本扭曲
- 23. 關於扭曲的文檔
- 24. IE中的文本扭曲
- 25. 驗證控件扭曲UI
- 26. 扭曲和ULIMIT
- 27. ImageMagick扭曲
- 28. 扭曲效果
- 29. 學習扭曲
- 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