Reputation: 311
I am not sure if this topic have been answered or not, if was I am sorry:
I have a simple python script the sends all files in one folder:
Client:
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);
Server:
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);
I know this not best server ever...but is what I know. This just work for a folder with small files because if I send big files(like 5mb...) it crashes because the time the client waits for the server is not enough.
So my question is how can I send the files to the server without client need to wait??or know exactly how many time the client needs to wait for the server to receive the file?? Some code that does the same but handling any file size, any help?
Upvotes: 2
Views: 6525
Reputation: 365767
TCP sockets are byte streams, not message streams. If you want to send a series of separate messages (like your separate files), you need to define a protocol, and then write a protocol handler. There is no way around that; just guessing at the timing or trying to take advantage of packet boundaries cannot possibly work.
The blog post linked above shows one way to do it. But you can do it with string delimiters if you want. But you have to deal with two problems:
read
packet, not just at the end."2929"
at the end of one read, and the other "29"
at the start of the next.The usually way you do that is to accumulate a buffer, and search for the delimiter anywhere in the buffer. Something like this:
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]
Meanwhile, you have another problem with your delimiter: There's nothing stopping it from appearing in the files you're trying to transmit. For example, what if you tried to send your script, or this web page?
That's one of the reasons that other protocols are often better than delimiters, but this isn't hard to deal with: just escape any delimiters found in the files. Since you're sending the whole file at once, you can just use replace
on right before the sendall
, and the reverse replace
right before the split
.
Upvotes: 3