[英]python socket file transfer
我正在嘗試通過套接字寫入傳輸文件或數據塊。 我覺得好像我正在重新發明輪子,但我對一個簡單的解決方案的搜索失敗了(我發現的一切都太簡單或太復雜)。 服務器將在運行python 2.5.4的手機上運行。 預期的應用是在電話和主機之間同步音樂文件。
這是我所擁有的內容,似乎有效。 我發送並收到“確定”以分解流。
是來回發送'ok'作為停止位來分解數據流是一種合理的技術嗎?
有沒有標准的方法來做到這一點?
考慮到手機內存和處理能力的限制,在手機上運行任何類型的庫服務器(ftp,http)都不是一個有用的解決方案。
服務器:
import socket
c = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
c.bind(('', 1234))
c.listen(1)
s,a = c.accept()
while True:
data = s.recv(1024)
cmd = data[:data.find('\n')]
if cmd == 'get':
x, file_name, x = data.split('\n', 2)
s.sendall('ok')
with open(file_name, 'rb') as f:
data = f.read()
s.sendall('%16d' % len(data))
s.sendall(data)
s.recv(2)
if cmd == 'end':
s.close()
c.close()
break
客戶:
import socket
s = socket.socket()
s.connect(('192.168.1.2', 1234))
def get_file(s, file_name):
cmd = 'get\n%s\n' % (file_name)
s.sendall(cmd)
r = s.recv(2)
size = int(s.recv(16))
recvd = ''
while size > len(recvd):
data = s.recv(1024)
if not data:
break
recvd += data
s.sendall('ok')
return recvd
print get_file(s, 'file1')
print get_file(s, 'file2')
s.sendall('end\n')
是來回發送'ok'作為停止位來分解數據流是一種合理的技術嗎?
大多數協議使用一些終結器或另一個。 流行的替代方案是'\\ r \\ n','\\ r \\ n \\ r \\ n'或EOF(ctrl + d),但這些只是任意選擇,並且沒有比你的'ok'更差或更好,只要你的客戶和服務器知道如何處理它。
你的代碼看起來不錯。
您實際上不需要跨文件大小發送。 您可以使用while True
,因為檢查if not data: break
將停止循環。
while True:
data = s.recv(1024)
if not data: print " Done "; break
recvd += data
另外,為什么你發送'ok'是對方不檢查它? 你只是在每邊跳過2個字節。
你不需要迎合多個客戶嗎? 不需要多線程?
你可以看看這個實現。 它還負責文件是否在子目錄中。 這是鏈接 !
服務器
import socket
import os
print('Waiting for clinet to connect...')
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.bind(('', 1234))
c.listen(1)
s, a = c.accept()
print('Connected. Going to receive file.')
s.sendall('getfilename')
filename = s.recv(1024)
if '/' in filename:
dir = os.path.dirname(filename)
try:
os.stat(dir)
except:
print('Directory does not exist. Creating directory.')
os.mkdir(dir)
f = open(filename, 'wb')
print('Filename: ' + filename)
while True:
s.sendall('getfile')
size = int(s.recv(16))
print('Total size: ' + str(size))
recvd = ''
while size > len(recvd):
data = s.recv(1024)
if not data:
break
recvd += data
f.write(data)
#print(len(recvd))
break
s.sendall('end')
print('File received.')
s.close()
c.close()
f.close()
客戶
import socket
import sys
if len(sys.argv) > 1 :
print('Trying to connect...')
s = socket.socket()
s.connect(('127.0.0.1', 1234))
print('Connected. Wating for command.')
while True:
cmd = s.recv(32)
if cmd == 'getfilename':
print('"getfilename" command received.')
s.sendall(sys.argv[1])
if cmd == 'getfile':
print('"getfile" command received. Going to send file.')
with open(sys.argv[1], 'rb') as f:
data = f.read()
s.sendall('%16d' % len(data))
s.sendall(data)
print('File transmission done.')
if cmd == 'end':
print('"end" command received. Teminate.')
break
有沒有標准的方法來做到這一點?
是。 http://www.faqs.org/rfcs/rfc959.html
描述執行此操作的標准方法。
這是一個實現: http : //docs.python.org/library/ftplib.html
rsync
是在兩台計算機之間同步文件的標准方法。 你可以用這樣的http://code.activestate.com/recipes/577518-rsync-algorithm/在Python中編寫它,或者你可以像這樣http://freshmeat.net/projects/pysync/包裝C庫並進行一些調整比如用MD5替換MD4。
或者,如果你想在套接字級別這樣做,你真的應該使用asyncore asynchat。 這是一個用asynchat http://pyftpdlib.googlecode.com/svn-history/r20/trunk/pyftpdlib/FTPServer.py編寫的FTP服務器,但你應該先閱讀http://www.doughellmann.com/PyMOTW/asynchat /注意關於消息終結者點2的部分。許多網絡協議都做這樣的奇怪的事情,即有時他們發送和接收全行命令和響應,有時他們發送和接收任意數據的塊,前面是計數塊中有多少字節。 使用asynchat可以更輕松地處理這個問題,並且您的程序也可以更好地擴展。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.