この記事の例では、参照用にftpファイル転送を実現するためのpythonの特定のコードを共有しています。具体的な内容は次のとおりです。
主な手順は、次の手順に分けることができます。
サーバー側のコード:
import socket,os,time
import hashlib
server =socket.socket()
server.bind(('0.0.0.0',6666))
server.listen()print("待つ....")while True:
conn,addr = server.accept()print("new conn:",conn)while True:
data = conn.recv(1024)if not data:print("client is disconnection")break
cmd,filename = data.decode().split() #指示とファイル名を記録する
print(filename)
# ファイルが現在のディレクトリに存在するかどうかを確認します。ファイルはディレクトリではなくファイルである必要があります
if os.path.isfile(filename):
f =open(filename,'rb')
# m = hashlib.md5() #md5を作成します
file_size = os.stat(filename).st_size #stat()ファイルのサイズを返すことができます
conn.send((str(file_size)).encode()) #送信ファイルサイズ
conn.recv(1024) #返品情報を待っています
for line in f:
# m.updata(line)
conn.send(line)
# print("file md5",m.hexdigest()) #md5値を出力
f.close()
クライアントコード:
# Author: zjt
import socket
client = socket.socket()
client.connect(("0.0.0.0",6666))while True:
cmd =input(" :").strip()iflen(cmd)==0:continueif cmd.startswith("get"):
client.send(cmd.encode())
server_response = client.recv(1024)print("server response: ",server_response)
client.send(b"ready to recv file")
# ファイルの受信を開始します
file_total_size =int(server_response.decode())
received_size =0 #受信したファイルのサイズを記録します
filename = cmd.split()[1]
# 2つのディレクトリは一貫しているため、受信したファイル名を元のファイルと同じにすることはできません。
f =open(filename+".new","wb")while received_size < file_total_size:
data = client.recv(1024)
received_size +=len(data)
f.write(data)print("total:",file_total_size," present: ",received_size)else:print("file has received done!")
f.close()
client.close()
80Mファイル転送テストを使用します。効果は次のとおりです。
プログラムのアップグレード:
以前のコードでは検証用のmd5が追加されていませんでしたが、コードがアップグレードされました
サーバー側のコード:
import socket,os,time
import hashlib
server =socket.socket()
server.bind(('0.0.0.0',8888))
server.listen()print("待つ....")while True:
conn,addr = server.accept()print("new conn:",conn)while True:
data = conn.recv(1024)if not data:print("client is disconnection")break
cmd,filename = data.decode().split() #指示とファイル名を記録する
print(filename)
# ファイルが現在のディレクトリに存在するかどうかを確認します。ファイルはディレクトリではなくファイルである必要があります
if os.path.isfile(filename):
f =open(filename,'rb')
m = hashlib.md5() #md5を作成します
file_size = os.stat(filename).st_size #stat()ファイルのサイズを返すことができます
conn.send((str(file_size)).encode()) #送信ファイルサイズ
conn.recv(1024) #返品情報を待っています
for line in f:
m.update(line)
conn.send(line)print("file md5",m.hexdigest()) #md5値を出力
f.close()
conn.send(m.hexdigest().encode()) #md5を送信します
print("本当に送った",m.hexdigest().encode())print("send done")
server.close()
クライアントコード:
import socket
import hashlib
client = socket.socket()
client.connect(("0.0.0.0",8888))while True:
cmd =input(" :").strip()iflen(cmd)==0:continueif cmd.startswith("get"):
client.send(cmd.encode())
server_response = client.recv(1024)print("server response: ",server_response)
client.send(b"ready to recv file")
# ファイルの受信を開始します
file_total_size =int(server_response.decode())
received_size =0 #受信したファイルのサイズを記録します
filename = cmd.split()[1]
# 2つのディレクトリは一貫しているため、受信したファイル名を元のファイルと同じにすることはできません。
f =open(filename+".new","wb")
m = hashlib.md5()while received_size < file_total_size:
data = client.recv(1024)
received_size +=len(data)
m.update(data)
f.write(data)
# print("total:",file_total_size," present: ",received_size)else:
new_file_md5 = m.hexdigest()print("client file md5:",new_file_md5)print("file has received done!")print("total:",file_total_size," present: ",received_size)
f.close()
sever_file_md5 = client.recv(1024)print("client file md5:",new_file_md5)print("server file md5:",sever_file_md5)
client.close()
2つのプログラムはLinux環境で実行され、結果は次のようになります。
転送後にファイルサイズが少し大きくなり、md5の前後の値も異なり、ファイル転送が変更されたことを示していることがわかります。
次に、Windows環境で実行されているプログラムについて説明します。結果は次のとおりです。
この時点で、Windowsで問題がなく、ファイルサイズが同じであり、md5値も同じであることがわかります。
原因分析:
これは、Linuxで実行しているときに、最後のファイル転送中にスティッカブルパケットが発生し、md5値が送信されたため、ファイルが最後に受信され、md5データが一緒に送信されたために発生します。また、クライアントは受信した情報の一部として扱われ、すべて受信されます。したがって、クライアントはサーバーからmd5値を受け取りません。少し余分なのは、md5値のサイズです。
解決:
ファイルを受信するときは、現在受信できるファイルの数を確認します。1024より大きい場合は、1024サイズのファイルを受信します。それ以外の場合は、残りのすべてのファイルのみを受信して、最後に冗長データを受信しないようにします。
クライアントコードを変更するだけで、変更されたコードは次のとおりです。
import socket
import hashlib
client = socket.socket()
client.connect(("0.0.0.0",8888))while True:
cmd =input(" :").strip()iflen(cmd)==0:continueif cmd.startswith("get"):
client.send(cmd.encode())
server_response = client.recv(1024)print("server response: ",server_response)
client.send(b"ready to recv file")
# ファイルの受信を開始します
file_total_size =int(server_response.decode())
received_size =0 #受信したファイルのサイズを記録します
filename = cmd.split()[1]
f =open(filename+".new","wb")
m = hashlib.md5()while received_size < file_total_size:
# 前回の残り分をできるだけ多く受け取り、くっつかないように判断してください。
if file_total_size - received_size 1024:
size =1024else: #前回、残り金額
size = file_total_size - received_size
data = client.recv(size)
received_size +=len(data)
m.update(data)
f.write(data)else:
new_file_md5 = m.hexdigest()print("client file md5:",new_file_md5)print("file has received done!")print("total:",file_total_size," present: ",received_size)print("次の文はファイルを閉じます")
f.close()print("md5の受信を開始します")
sever_file_md5 = client.recv(1024)print("client file md5:",new_file_md5)print("server file md5:",sever_file_md5)
client.close()
以上が本稿の内容ですので、皆様のご勉強に役立てていただければ幸いです。
Recommended Posts