Python客户端/服务器发送的大尺寸文件
我不知道,如果这个主题已经回答与否,如果是不好意思:Python客户端/服务器发送的大尺寸文件
我有一个简单的Python脚本发送一个文件夹中的所有文件:
客户:
import os,sys, socket, time
def Send(sok,data,end="292929"):
sok.sendall(data + end);
def SendFolder(sok,folder):
if(os.path.isdir(folder)):
files = os.listdir(folder);
os.chdir(folder);
for file_ in files:
Send(sok,file_);#Send the file name to the server
f = open(file_, "rb");
while(True):
d = f.read();#read file
if(d == ""):
break;
Send(sok, d, "");#Send file data
f.close();
time.sleep(0.8);#Problem here!!!!!!!!!!!
Send(sok,"");#Send termination to the server
time.sleep(1);#Wait the server to write the file
os.chdir("..");
Send(sok,"endfile");#let the server know that we finish sending files
else:
Send("endfile")#If not folder send termination
try:
sok1 = socket.socket();
sok1.connect(("192.168.1.121",4444))#local ip
time.sleep(1);
while(True):
Send(sok1,"Enter folder name to download: ");
r = sok1.recv(1024);
SendFolder(sok1,r);
time.sleep(0.5);
except BaseException, e:
print "Error: " + str(e);
os._exit(1);
服务器:
import sys,os,socket,time
# receive data
def Receive(sock, end="292929"):
data = "";
while(True):
if(data.endswith(end)):
break;
else:
data = sock.recv(1024);
return data[:-len(end)];#return data less termination
def FolderReceive(sok):
while(True):
r = Receive(sok);# recv filename or folder termination("endfile")
if(r == "endfolder"):
print "Folder receive complete.";
break;
else:
filename = r;#file name
filedata = Receive(sok);# receive file data
f = open(filename,"wb");
f.write(filedata);
f.close();#finish to write the file
print "Received: " + filename;
try:
sok1 = socket.socket();
sok1.bind(("0.0.0.0",4444));
sok1.listen(5);
cl , addr = sok1.accept();#accepts connection
while(True):
r = Receive(cl);
sys.stdout.write("\n" + r);
next = raw_input();
cl.sendall(next);#send folder name to the client
FolderReceive(cl);
except BaseException, e:
print "Error: " + str(e);
os._exit(1);
我知道这有史以来最好的不是服务器...但什么 我知道。这只适用于文件夹较小的文件夹,因为如果我发送大文件(如5mb ...),它会崩溃,因为客户端等待服务器的时间是不够的。
所以我的问题是我怎么能发送文件到服务器,而无需客户端需要等待?或确切地知道客户端需要等待服务器接收文件多少时间?一些相同的代码,但处理任何文件大小,有什么帮助?
TCP sockets are byte streams, not message streams。如果你想发送一系列单独的消息(比如你的单独文件),你需要定义一个协议,然后编写一个协议处理程序。这是没有办法的;只是在猜测时间或试图利用数据包边界不可能工作。
上面链接的博客文章显示了一种方法。但是,如果你愿意,你可以用字符串分隔符来完成。但是你必须处理两个问题:
- 定界符可以出现在
read
数据包中的任何地方,而不仅仅是结尾。 - 分隔符可以在数据包边界上分开 - 您可以在一次读取结束时获得
"2929"
,在下一次读取结束时获得另一个"29"
。
你这样做的通常方法是累积一个缓冲区,然后在缓冲区中的任意位置搜索分隔符。事情是这样的:
def message(sock, delimiter):
buf = ''
while True:
data = sock.read(4096)
if not data:
# If the socket closes with no delimiter, this will
# treat the last "partial file" as a complete file.
# If that's not what you want, just return, or raise.
yield buf
return
buf += data
messages = buf.split(delimiter)
for message in messages[:-1]:
yield message
buf = message[-1]
同时,你有你的分隔符另一个问题:没有什么出现在你试图传送文件停止它。例如,如果您尝试发送您的脚本或此网页,该怎么办?
这是其他协议通常比分隔符更好的原因之一,但这并不难处理:只需转义在文件中找到的任何分隔符即可。由于您一次发送整个文件,因此您可以在sendall
之前恰好使用replace
,在split
之前恰好使用replace
。
非常感谢,我想我会在所有的代码中看起来更好,看看最好的方法来使它工作!我知道上面的代码只是一个大混乱! – lazyy001
是的我知道python不需要“;”和“()”,但我喜欢这样做! – lazyy001
嗯,它让你的代码难以阅读,因为有经验的Python开发人员 - 你想在这里帮助你的人。 – abarnert
同时,'if(data.endswith(end)):'不会起作用,因为结束标记可能来自数据包中的_anywhere_,而不仅仅是数据包的末尾。 (如果你想发送的文件中出现“292929”字符串,例如,如果你尝试发送一个包含这个脚本的目录,那么这也将是一个大问题。) – abarnert