2016-04-12 10 views
-1

"サーバー"コンピュータの複数の "クライアント"コンピュータを接続し、それらのクライアントを使用してFTP(pyftplibとpyftpdlib )を使用してファイルと結果を転送します。python FTPスクリプトでエラーチェック機能を構築する

スクリプトは、サーバー上にファイル、処理、結果という3つのフォルダを作成して動作します。クライアントはFTPでサーバに接続し、 "Files"フォルダにアクセスし、処理のためにファイルを取得し、処理中に "Processing"フォルダに転送します。次に、処理が終了すると、クライアントは処理フォルダからファイルを削除し、結果を「結果」フォルダにコピーします。

これは、サーバー側とクライアント側の両方で正しく機能しています。私が抱えている問題は、クライアントの1つがエラーを生成せずに途中で切断された場合(PCが切断されて停電した場合)、サーバーはクライアントがファイルを処理しているかのように脅威になり、 「処理中」フォルダ。私が望むのは、エラーが発生したときに、「処理中」フォルダのファイルが「ファイル」フォルダに戻るエラーチェック機能です。ここで

はサーバーFTPコード

def main(): 
    authorizer = DummyAuthorizer() 
    authorizer.add_user('client', 'password', '.', perm='elradfmwM') 
    authorizer.add_anonymous(os.getcwd()) 

    handler = FTPHandler 
    handler.authorizer = authorizer 
    handler.banner = "FTP Server." 
    address = ('', port) 
    server = FTPServer(address, handler) 
    server.max_cons = 256 
    server.max_cons_per_ip = 50 
    server.serve_forever() 


if __name__ == '__main__': 
    main() 

そして、ここでは、クライアントのFTPコードである:助けを

while True: 
    ftp = ftplib.FTP() 
    ftp.connect(arguments.host_ip, arguments.host_port) 
    ftp.login("client", "password") 
    print ftp.getwelcome() 
    ftp.retrlines('LIST') 
    ftp.retrbinary('RETR Output.txt', open('Output.txt', 'wb').write) 
    ftp.retrbinary('RETR dicionario.json', open('dicionario.json', 'wb').write) 
    with open('dicionario.json') as json_file: 
     json_data = json.load(json_file) 
    receptor_file = json_data['--receptor'] 
    print 'Retrieving receptor file ' + receptor_file 
    ftp.retrbinary('RETR ' + receptor_file, open(receptor_file, 'wb').write) 
    ftp.cwd('Files') 
    ftp.retrlines('LIST') 
    filename = ftp.nlst()[0] 
    print 'Getting ' + filename 
    ftp.retrbinary('RETR ' + filename, open(filename, 'wb').write) 
    with open("Output.txt", "a") as input_file: 
     input_file.write('ligand = %s' %filename) 
     input_file.close() 
    ftp.delete(filename) 
    ftp.cwd('../Processing') 
    ftp.storbinary('STOR ' + filename, open(filename, 'rb')) 
    ftp.quit() 

    print "Processing" 
    return_code = subprocess.call(calls the program for processing files) 
    if return_code == 0: 
     print """Done!""" 
     ftp.connect(arguments.host_ip, arguments.host_port) 
     ftp.login("client", "password") 
     ftp.cwd('Results') 
     ftp.storbinary('STOR ' + os.path.splitext(filename)[0] + '_out.pdbqt', open (os.path.splitext(filename)[0] + '_out.pdbqt')) 
     ftp.cwd('../Processing') 
     ftp.delete(filename) 


     ftp.quit() 
    else: 
     print """Something is technically wrong...""" 
     ftp.connect(arguments.host_ip, arguments.host_port) 
     ftp.login("client", "password") 
     ftp.cwd('Files') 
     ftp.storbinary('STOR ' + filename, open(filename, 'rb')) 
     ftp.cwd('../Processing') 
     ftp.delete(filename) 
     ftp.quit() 

ありがとう!

答えて

0

ので、このコードをいじる半月後、私は最終的に、クライアントは、私は、サーバーが各クライアントを識別するための方法を作るために持っていた接続

ファーストをキャンセルすると、それが働かせました。私はpyftpdlibにカスタムハンドラを作成した。これは、その後、9文字のログイン名とパスワード

を生成

def handler_generation(size=9, chars=string.ascii_uppercase + string.digits): 
    return ''.join(random.choice(chars) for i in range (size)) 

:代わりに、彼らは唯一のユーザでログインすることで、私は2つの異なる機能を、接続ごとに特定のユーザーを作成しましただから、

class MyHandler(FTPHandler): 
    def on_login(self, username): 
    if username == "client": 
     user_login = handler_generation() 
     user_password = handler_generation() 
     global authorizer 
     authorizer.add_user(user_login, user_password, '.', perm='elradfmwM') 
     credentials = open("Credentials.txt",'w') 
     credentials.write(user_login) 
     credentials.write("\n") 
     credentials.write(user_password) 
     credentials.close() 
    else: 
     pass 

、クライアントが「クライアント」にログインして接続するとき、サーバは9文字のログイン名とパスワードを生成して、「Credentials.txt」でクライアントに送信します:、およびon_login機能を使用ファイル。クライアント側では、次のようになります。

ftp.login("client", "password") 
    ftp.retrbinary('RETR Credentials.txt', open('Credentials.txt', 'wb').write) 
    ftp.quit() 
    with open('Credentials.txt') as credential_file: 
     lines = credential_file.readlines() 
     credential_login = lines[0].split("\n")[0] 
     credential_password = lines[1].split("\n")[0] 
    ftp.connect(arguments.host_ip, arguments.host_port) 
    ftp.login(credential_login, credential_password) 

これでクライアントはそれぞれ固有のログインに接続します。クライアント側では、完了したタスクごとに、クライアントは特定のログイン用に名前の付いたファイルを送信するようにしました。

:私は、ハンドラクラスの他の機能、on_disconnectを使用し、その後

​​

:私はまた、クライアントは、彼らはそれが簡単にサーバーがファイルを見つけるために作るために処理されたファイルには、自分のログイン名を追加し作られました

def on_disconnect(self): 
    if self.username == "client": 
     pass 
    else: 
     if os.path.isfile(self.username): 
      pass 
     else: 
      for fname in os.listdir("Processing"): 
       if fname.startswith(self.username): 
        shutil.move("Processing/" + fname, "Files") 
        os.rename("Files/" + fname, "Files/" + fname[9::]) 

    print self.remote_ip, self.remote_port,self.username, "disconnected" 
    pass 

クライアントが切断するたびに、サーバーはフォルダを検索して、クライアントがハンドラファイルを送信したかどうかを確認します。それがなければ、サーバーはファイルを "Files"フォルダーに移動します。これは、まだ処理されていないファイルがあるフォルダーです。

quitコマンドを送信せずに失敗したクライアントをサーバーから切断するには、pyftpdlibのタイムアウト機能を使用しました。アクティブなクライアントが誤ってタイムアウト、私は、サーバー毎N秒で何かをすることを、クライアントにスレッドを実装しないことを確認するには:

class perpetualTimer(): 

def __init__(self,t,hFunction): 
    self.t=t 
    self.hFunction = hFunction 
    self.thread = Timer(self.t,self.handle_function) 

def handle_function(self): 
    self.hFunction() 
    self.thread = Timer(self.t,self.handle_function) 
    self.thread.start() 

def start(self): 
    self.thread.start() 

def cancel(self): 
    self.thread.cancel() 

def NotIdle(): 
    Doing something here 

t = perpetualTimer(10, NotIdle) 
t.start() 

(私はまっすぐここに誰かからコピーされ、この特定のコードが)

また、現在、サーバーとクライアントの両方が機能し、独自のエラーチェック機能を備えています。

誰かが同様の問題に遭遇した場合のために、私はこの回答をここに入れています。

ありがとうございます!

関連する問題