Python sending a file over sockets - python

I am trying to write a script that requires files to be sent from server to clients and am having issues with the files being completely sent when the destination is not the local host. So when the server and client are on different machines the client seems to receive the file faster then the server is sending it and stops receiving early. An example is if I try to send a 200 MB file over the client stops receiving it around usually around 180 MB.
Here are the portions of the script that send and receive files.
send file
def t_handle(client, address, s):
file_size = str(os.stat("path to file to send").st_size)
print file_size
client.send(file_size)
work_file = open("path to fil to send", "rb")
print "sending file"
file_size = int(file_size)
while file_size > 0:
buffer = work_file.read(1024)
client.send(buffer)
file_size -= 1024
print file_size
print "done"
Receive file
def main():
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.settimeout(90)
server.connect((host, port))
file_size = int(server.recv(1024))
print "receiving file"
file_size = int(file_size)
print file_size
f = open("test_output.mkv", "wb+")
while file_size > 0:
work_file = server.recv(1024)
f.write(work_file)
file_size -= 1024
print file_size
f.close()
print "done"
return 0
Any help would be greatly appreciated.

The argument to socket.recv() is the maximum number of bytes that the call will return, and there's no guarantee that you'll actually get that many on any given call:
while file_size > 0:
work_file = server.recv(1024)
f.write(work_file)
file_size -= 1024
print file_size
If you receive fewer than 1024 bytes on each call, yet subtract that many from your target byte count, your code will act as if it's complete before it actually is.
Try modifying it to something like:
while file_size > 0:
work_file = server.recv(1024)
f.write(work_file)
# subtract the actual number of bytes received
file_size -= len(work_file)
print file_size

Related

Python Client Server UDP File Transfer with ACKs

As an exercise for the university, I have to create a client-server application that allows you to send files from client to server and vice versa. The only part that I cannot implement concerns the sending of the ACKs (that is required) to confirm the correct reception of the packet.
Regarding what I did so far, the code works fine.
How can I implement it?
Here is the send and receive parts of code:
def send_file(address, chosen_file_name):
# Server information
host, port = address
# File buffer
buffer_size = 4096 * 10
# Transfer file name
filename = chosen_file_name
# File size
file_size = os.path.getsize(filename)
# Create socket link
s = sk.socket(sk.AF_INET, sk.SOCK_DGRAM)
s.setsockopt(sk.SOL_SOCKET, sk.SO_REUSEADDR, 1)
print(f'Server connection {host}:{port}')
s.connect((host, port))
print('Successful connection to server')
# Send file name and size, which must be encoded
sleep(1)
s.send(f'{filename}{Separator}{file_size}'.encode('utf-8'))
# File transfer
progress = tqdm.tqdm(range(file_size), f'Send {filename}', unit='B', unit_divisor=1024)
with open(filename, 'rb') as f:
# Read the file
for _ in progress:
bytes_read = f.read(buffer_size)
if not bytes_read:
print('Exit transmission, transmission is complete!')
s.sendall('file_upload_exit'.encode('utf-8'))
break
s.sendall(bytes_read)
progress.update(len(bytes_read))
sleep(0.001)
# Close resources
s.close()
def receive_file(address):
# File buffer
buffer_size = 4096 * 10
udp_socket = sk.socket(sk.AF_INET, sk.SOCK_DGRAM)
udp_socket.setsockopt(sk.SOL_SOCKET, sk.SO_REUSEADDR, 1)
udp_socket.bind(address)
recv_data = udp_socket.recvfrom(buffer_size)
recv_file_info = recv_data[0].decode('utf-8') # Storing the received data, Filename
c_address = recv_data[1] # Storing the address information of the customer
print(f'Client {c_address} Connect')
chosen_file_name, file_size = recv_file_info.split(Separator)
# Get the name of the file, Size
chosen_file_name = os.path.basename(chosen_file_name)
file_size = int(file_size)
# File receiving processing
progress = tqdm.tqdm(range(file_size), f'Receive {chosen_file_name}', unit='B', unit_divisor=1024, unit_scale=True)
with open('r_' + chosen_file_name, 'wb') as f:
for _ in progress:
# Read data from client
bytes_read = udp_socket.recv(buffer_size)
# If there is no data transfer content
if bytes_read == b'file_download_exit':
print('Complete transmission!')
break
# Read and write
f.write(bytes_read)
# Update progress bar
progress.update(len(bytes_read))
udp_socket.close()

Python Sockets multiple file transfers

So I have a python program that basically let's the client connect to the server and send it an excel file which is used as an input for an optimization problem. I then want the server to send the output of this optimization (also an excel file) back to the client. The model itself takes about a minute to solve, and I think this is causing some issues with the client trying to receive the output 'too early'.
The client code:
SEPARATOR = "<SEPARATOR>"
BUFFER_SIZE = 4096
HEADER = 64
HEADERSIZE = 10
port = 1234
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
host = "123.45.678.910"
s = socket.socket()
s.connect((host, port))
filename = "input/Model_Input.xlsx"
filesize = os.path.getsize(filename)
s.send(f"{filename}{SEPARATOR}{filesize}".encode())
with open(filename, "rb") as f:
while True:
bytes_read = f.read(BUFFER_SIZE)
if not bytes_read:
break
s.sendall(bytes_read)
out_received = s.recv(BUFFER_SIZE).decode()
out_filename, out_filesize = out_received.split(SEPARATOR)
out_filename = os.path.basename(out_filename)
out_filesize = int(out_filesize)
with open(out_filename, "wb") as h:
while True:
out_bytes_read = s.recv(BUFFER_SIZE)
if not out_bytes_read:
break
h.write(out_bytes_read)
And the server code:
SERVER_PORT = 1234
SERVER_HOST = socket.gethostbyname(socket.gethostname())
BUFFER_SIZE = 4096
SEPARATOR = "<SEPARATOR>"
s = socket.socket()
s.bind((SERVER_HOST, SERVER_PORT))
s.listen(5)
client_socket, address = s.accept()
received = client_socket.recv(BUFFER_SIZE).decode()
filename, filesize = received.split(SEPARATOR)
filename = os.path.basename(filename)
filesize = int(filesize)
with open(filename, "wb") as f:
while True:
bytes_read = client_socket.recv(BUFFER_SIZE)
if not bytes_read:
break
f.write(bytes_read)
##################
## MODEL CODE ##
##################
outfilename = 'Model_Output.xlsx'
outfilesize = os.path.getsize(filename)
client_socket.send(f"{outfilename}{SEPARATOR}{outfilesize}".encode())
with open(outfilename, "rb") as h:
while True:
# read the bytes from the file
bytes_readed = h.read(BUFFER_SIZE)
if not bytes_readed:
break
client_socket.sendall(bytes_readed)
I am able to send the input file to the server and get the model to run, and save the output to storage. However, as soon as I add in the part to try send it back to the client, it gets stuck. It still sends and receives the input file successfully, but then the model never runs. Neither the client nor the server disconnect, they both just seem to be stuck.
Thank you
I can be very difficult for someone (i.e. me) to remotely debug this type of code, so I can't really point to a particular line of code that is necessarily the problem. If, however, your client and server are running on the same machine, then there is a potential problem in the client code that begins:
with open(out_filename, "wb") as h:
while True:
out_bytes_read = s.recv(BUFFER_SIZE)
if not out_bytes_read:
break
h.write(out_bytes_read)
When the open is executed, this sets the file size to 0. The server, meanwhile is reading this file to transmit it to the file and can possibly find that there are now only 0 bytes. But it has already sent a "header" saying that there are N bytes where N is non-zero. But that is a different problem than the one you describe. But it could be happening in the other direction, also. That is, when the client is sending the file and the server is opening the file for output, it is now zeroing out the file that the client is still reading. The code below solves that problem in both directions. Of course, if your client and server are on different computers not accessing the same files concurrently, then what I have described is not an issue. Not yet, anyway.
I can, however, offer a slightly different approach, which does seem to work:
See the Using a Socket section from the Socket Programming HOWTO article in the Python 3 Manual. I have adopted the suggestion to use fixed length messages. It's a little more laborious, perhaps, but also a bit more fullproof. That means that if you want to transmit the filename, you have to first transmit the length of the encoded filename as fixed length length message (3 bytes can handle encoded filenames up to 999 bytes in length) and then you can transmit the encode filename. Similarly, we transmit the length of a file as a 9 byte length (left-padded with zeroes), which can handle file sizes up to 999,999,999 bytes (I set the width of 9 arbitrarily). I have two functions, receive_msg and send_msg that will robustly send and receive complete byte messages and can be used by both the client and server. These are modeled on the MySocket.mysend and MySocket.myreceive methods from the article.
I assumed that the server should be able to handle more than one request before terminating. In fact, it should be able to handle requests concurrently. To that end the server passes a request to a thread pool worker function, process_request, for processing. It wasn't clear what the nature of the so-called "Model Code" was. Assuming the function that performs this computation, process_model, is CPU-intensive, process_requestis passed a multiprocessing pool instance that can be used to perform the process_model processing so that the CPU-intensive portion of processing will not be limited by the Global Interpreter Lock. If there is no real CPU-intensive processing involved, then remove the code that created the multiprocessing pool and then call process_model as a regular function.
Server Code
import socket
from multiprocessing.pool import Pool, ThreadPool
import os.path
BUFFER_SIZE = 4096
SERVER_PORT = 1234
SERVER_HOST = socket.gethostbyname(socket.gethostname())
def receive_msg(sock, msg_length):
chunks = []
bytes_recd = 0
while bytes_recd < msg_length:
chunk = sock.recv(min(msg_length - bytes_recd, BUFFER_SIZE))
if chunk == b'':
raise RuntimeError("socket connection broken")
chunks.append(chunk)
bytes_recd = bytes_recd + len(chunk)
return b''.join(chunks)
def send_msg(sock, msg):
msg_length = len(msg)
totalsent = 0
while totalsent < msg_length:
sent = sock.send(msg[totalsent:])
if sent == 0:
raise RuntimeError("socket connection broken")
totalsent = totalsent + sent
def server():
s = socket.socket()
s.bind((SERVER_HOST, SERVER_PORT))
s.listen(5)
process_pool = Pool(5)
thread_pool = ThreadPool(5)
while True:
client_socket, address = s.accept()
thread_pool.apply_async(process_request, args=(process_pool, client_socket))
def process_request(process_pool, s):
# Fixed length fields:
# width 3 for filename length, followed by filename, width 9 for filesize
filename_size = int(receive_msg(s, 3).decode())
filename = receive_msg(s, filename_size).decode()
filename = os.path.basename(filename)
filesize = int(receive_msg(s, 9).decode())
msg = receive_msg(s, filesize)
with open(filename, "wb") as f:
f.write(msg)
# Assuming processing the model is CPU-intensive,
# we use a process pool for doing that:
out_filename = process_pool.apply(process_model, args=(filename,))
out_filesize = os.path.getsize(out_filename)
encoded_filename = out_filename.encode()
msg1 = b"%03d%s%09dfilesize" % (len(encoded_filename), encoded_filename, out_filesize)
with open(out_filename, "rb") as h:
msg2 = h.read()
send_msg(s, msg1)
send_msg(s, msg2)
def process_model(filename):
...
# Returned filename should probably be a function of the passed filename
return 'Model_Output.xlsx' # name of the output file
if __name__ == '__main__':
server()
Client Code
import socket
import os.path
BUFFER_SIZE = 4096
port = 1234
host = "123.45.678.910"
def receive_msg(sock, msg_length):
chunks = []
bytes_recd = 0
while bytes_recd < msg_length:
chunk = sock.recv(min(msg_length - bytes_recd, BUFFER_SIZE))
if chunk == b'':
raise RuntimeError("socket connection broken")
chunks.append(chunk)
bytes_recd = bytes_recd + len(chunk)
return b''.join(chunks)
def send_msg(sock, msg):
msg_length = len(msg)
totalsent = 0
while totalsent < msg_length:
sent = sock.send(msg[totalsent:])
if sent == 0:
raise RuntimeError("socket connection broken")
totalsent = totalsent + sent
def client():
s = socket.socket()
s.connect((host, port))
filename = "input/Model_Input.xlsx"
filesize = os.path.getsize(filename)
# Fixed length fields:
# width 3 for filename length, followed by filename, width 9 for filesize
encoded_filename = filename.encode()
msg1 = b"%03d%s%09dfilesize" % (len(encoded_filename), encoded_filename, filesize)
with open(filename, "rb") as f:
msg2 = f.read()
send_msg(s, msg1)
send_msg(s, msg2)
out_filename_size = int(receive_msg(s, 3).decode())
out_filename = receive_msg(s, out_filename_size).decode()
out_filename = os.path.basename(out_filename)
out_filesize = int(receive_msg(s, 9).decode())
msg = receive_msg(s, out_filesize)
with open(out_filename, "wb") as h:
h.write(msg)
if __name__ == '__main__':
client()
Update
The entire programming can greatly be simplified by implementing the service as a Remote Procedure Call. The code is based on Python Cookbook, 3rd Edition:
Server
import socket
import pickle
from multiprocessing.connection import Listener
from threading import Thread
from multiprocessing.pool import Pool
import os.path
SERVER_PORT = 1234
SERVER_HOST = socket.gethostbyname(socket.gethostname())
class RPCHandler:
def __init__(self):
self._functions = { }
def register_function(self, func):
self._functions[func.__name__] = func
def handle_connection(self, connection):
try:
while True:
# Receive a message
func_name, args, kwargs = pickle.loads(connection.recv())
# Run the RPC and send a response
try:
r = self._functions[func_name](*args,**kwargs)
connection.send(pickle.dumps(r))
except Exception as e:
connection.send(pickle.dumps(e))
except EOFError:
pass
def server():
global process_pool
handler = RPCHandler()
handler.register_function(process_request)
sock = Listener((SERVER_HOST, SERVER_PORT))
process_pool = Pool(5)
while True:
client = sock.accept()
t = Thread(target=handler.handle_connection, args=(client,))
t.daemon = True
t.start()
def process_request(filename, contents):
filename = os.path.basename(filename)
with open(filename, "wb") as f:
f.write(contents)
# Assuming processing the model is CPU-intensive,
# we use a process pool for doing that:
out_filename = process_pool.apply(process_model, args=(filename,))
with open(out_filename, "rb") as h:
out_contents = h.read()
return (out_filename, out_contents)
def process_model(filename):
...
# Returned filename should probably be a function of the passed filename
return 'Model_Output.xlsx' # name of the output file
if __name__ == '__main__':
server()
Client
import pickle
import socket
import os.path
from multiprocessing.connection import Client
port = 1234
host = "123.45.678.910"
class RPCProxy:
def __init__(self, connection):
self._connection = connection
def __getattr__(self, name):
def do_rpc(*args, **kwargs):
self._connection.send(pickle.dumps((name, args, kwargs)))
result = pickle.loads(self._connection.recv())
if isinstance(result, Exception):
raise result
return result
return do_rpc
def client():
c = Client((host, port))
proxy = RPCProxy(c)
filename = "input/Model_Input.xlsx"
with open(filename, "rb") as f:
contents = f.read()
(out_filename, out_contents) = proxy.process_request(filename, contents)
out_filename = os.path.basename(out_filename)
with open(out_filename, "wb") as h:
h.write(out_contents)
if __name__ == '__main__':
client()

python socket file transfer verified with sha256 not working, but only sometimes?

Client side:
def send_file_to_hashed(data, tcpsock):
time.sleep(1)
f = data
flag = 0
i=0
tcpsock.send(hashlib.sha256(f.read()).hexdigest())
f.seek(0)
time.sleep(1)
l = f.read(BUFFER_SIZE-64)
while True:
while (l):
tcpsock.send(hashlib.sha256(l).hexdigest() + l)
time.sleep(1)
hashok = tcpsock.recv(6)
if hashok == "HASHOK":
l = f.read(BUFFER_SIZE-64)
flag = 1
if hashok == "BROKEN":
flag = 0
if not l:
time.sleep(1)
tcpsock.send("DONE")
break
return (tcpsock,flag)
def upload(filename):
flag = 0
while(flag == 0):
with open(os.getcwd()+'\\data\\'+ filename +'.csv', 'rU') as UL:
tuplol = send_file_to_hashed(UL ,send_to_sock(filename +".csv",send_to("upload",TCP_IP,TCP_PORT)))
(sock,flagn) = tuplol
flag = flagn
time.sleep(2)
sock.close()
Server Side:
elif(message == "upload"):
message = rec_OK(self.sock)
fis = os.getcwd()+'/data/'+ time.strftime("%H:%M_%d_%m_%Y") + "_" + message
f = open(fis , 'w')
latest = open(os.getcwd()+'/data/' + message , 'w')
time.sleep(1)
filehash = rec_OK(self.sock)
print("filehash:" + filehash)
while True:
time.sleep(1)
rawdata = self.sock.recv(BUFFER_SIZE)
log.write("rawdata :" + rawdata + "\n")
data = rawdata[64:]
dhash = rawdata[:64]
log.write("chash: " + dhash + "\n")
log.write("shash: " + hashlib.sha256(data).hexdigest() + "\n")
if dhash == hashlib.sha256(data).hexdigest():
f.write(data)
latest.write(data)
self.sock.send("HASHOK")
log.write("HASHOK\n" )
print"HASHOK"
else:
self.sock.send("HASHNO")
print "HASHNO"
log.write("HASHNO\n")
if rawdata == "DONE":
f.close()
f = open(fis , 'r')
if (hashlib.sha256(f.read()).hexdigest() == filehash):
print "ULDONE"
log.write("ULDONE")
f.close()
latest.close()
break
else:
self.sock.send("BROKEN")
print hashlib.sha256(f.read()).hexdigest()
log.write("BROKEN")
print filehash
print "BROKEN UL"
f.close()
So the data upload is working fine in all tests that i ran from my computer, even worked fine while uploading data over my mobile connection and still sometimes people say it takes a long time and they kill it after a few minutes. the data is there on their computers but not on the server. I don't know what is happening please help!
First of all: this is unrelated to sha.
Streaming over the network is unpredictable. This line
rawdata = self.sock.recv(BUFFER_SIZE)
doesn't guarantee that you read BUFFER_SIZE bytes. You may have read only 1 byte in the worst case scenario. Therefore your server side is completely broken because of the assumption that rawdata contains whole message. It is even worse. If the client sends command and hash fast you may get e.g. rawdata == 'DONEa2daf78c44(...) which is a mixed output.
The "hanging" part just follows from that. Trace your code and see what happens when the server receives partial/broken messages ( I already did that in my imagination :P ).
Streaming over the network is almost never as easy as calling sock.send on one side and sock.recv on the other side. You need some buffering/framing protocol. For example you can implement this simple protocol: always interpret first two bytes as the size of incoming message, like this:
client (pseudocode)
# convert len of msg into two-byte array
# I am assuming the max size of msg is 65536
buf = bytearray([len(msg) & 255, len(msg) >> 8])
sock.sendall(buf)
sock.sendall(msg)
server (pseudocode)
size = to_int(sock.recv(1))
size += to_int(sock.recv(1)) << 8
# You need two calls to recv since recv(2) can return 1 byte.
# (well, you can try recv(2) with `if` here to avoid additional
# syscall, not sure if worth it)
buffer = bytearray()
while size > 0:
tmp = sock.recv(size)
buffer += tmp
size -= len(tmp)
Now you have properly read data in buffer variable which you can work with.
WARNING: the pseudocode for the server is simplified. For example you need to check for empty recv() result everywhere (including where size is calculated). This is the case when the client disconnects.
So unfortunately there's a lot of work in front of you. You have to rewrite whole sending and receving code.

File transferring, File can't be opend after transfer

I am currently working on a file transfer server and ran into
a problem. I am able to transfer the file completly and it works perefect,
But when the client that received the file cannot open it through python.
What I mean is that if I transferr a file, I can see it in the dic of the client the received it, but it cannot open it and I get an:IOError that the file doesn't exist.
The server:
def download_manager(self, sock, ADDR, name):
sock.send('Starting file download: '+name)
# Getting the socket that has the file
# Getting the user ip address
BUFSIZ = 1024
fileSock = socket(AF_INET, SOCK_STREAM)
fileSock.connect(ADDR)
print 'connected;'
# Starting the file request protocol.
tries = "2"
# sending number of retries.
fileSock.send(tries + "," + name)
sock.send(tries)
for i in range(int(tries)):
# Accepting the start message.
data, size = fileSock.recv(BUFSIZ).split(',')
sock.send(size)
size = int(size)
if data == 'Start':
fileSock.send('ok')
# Getting first data from the supplier.
data = fileSock.recv(BUFSIZ)
# Sending the data to the request client.
sock.send(data)
current_size = BUFSIZ
while current_size <= size:
# Getting data from the supplier.
data = fileSock.recv(BUFSIZ)
# The server "sleeps" in order to keep a synchronization between the client and the server.
# The client works slower than the server(It needs to save the file as well.
time.sleep(0.0001)
# Sending the data to the request client.
sock.send(data)
current_size += BUFSIZ
print current_size
# Receive for the request client the end message.
#sock.send(data)
data = sock.recv(1024)
if data == 'ok':
fileSock.send(data)
break
else:
fileSock.send(data)
else:
sock.send("wrong")
fileSock.close()
The sender client, Just the relevant part:
print "connection from:", addr
# From here on, the server works by the File-Transfer RFC.
# Accepting number of retries from the server and the name of the file.
data = clientsock.recv(self.BUFSIZ)
tries, name = data.split(',')
# Opening File.
f = file(name, mode='rb')
if not tries:
clientsock.close()
continue
try:
for i in range(int(tries)):
# Sending the file size.
clientsock.send('Start,'+str(self.file_size(name)))
# Accepting an ok.
ok = clientsock.recv(self.BUFSIZ)
if not ok:
continue
if ok == "ok":
# Sending the file.
clientsock.send(f.read(-1))
# Waiting for confirmation.
ok = clientsock.recv(self.BUFSIZ)
if ok == "ok":
break
else:
continue
f.close()
except IOError as e:
f.close()
print e
# An error has occurred, closing the socket.
#clientsock.send('End,None')
clientsock.close()
The recieve Client:
def get_file(self, name):
"""
This function receives and saves the requested file from the server.
:param name: The name of the file( How it is saved )
:return: None.
"""
name = name.split('.')
tries = int(self.sock.recv(self.BUFSIZ))
progress = 0
for i in range(tries):
f = file(name[0] + '.' + name[1], mode='wb')
final_size = int(self.sock.recv(self.BUFSIZ))
data = self.sock.recv(self.BUFSIZ)
f.write(data)
current_size = self.BUFSIZ
while current_size <= final_size:
progress = (float(current_size)/final_size)
if progress > 0.01:
self.app.progress = progress
data = self.sock.recv(self.BUFSIZ)
f.write(data)
current_size += self.BUFSIZ
f.close()
print "Current: " + str(current_size)
print "real: " + str(self.file_size(name[0] + '.' + name[1]))
print "Wanted: " + str(final_size)
self.app.progress = None
if self.file_size(name[0] + '.' + name[1]) == final_size:
print 'ok'
self.sock.send('ok')
break
else:
print 'Bad'
os.remove(name[0] + '.' + name[1])
self.sock.send('Bad')
continue
Any Help is welcomed!

How to send end of file without closing tcp socket

I am trying to send a file over a tcp socket in a peer to peer chat system coded in python. The receiving socket seems not to know that there is no more file to receive. The only way I can get the receiving socket to not anticipate the data that isn't coming is by closing the sending socket (using socket.shutdown(socket.SHUT_WR)). However, closing the sending socket is not an option because I need that socket to send other messages. I fisrt tried allocating a new port for file sending/receiving and failed. Now, I have tried creating an end of file "signal" but it does not get recognized on the receiving end as a message separate from the tcp segment, so I am stuck.
The sending code looks like this:
def sendFile(self,filePath):
try:
f = open(filePath, 'rb')
print 'file opened'
for soc in self.allClients.keys():
try:
f = open(filePath, 'rb')
except:
print "File does not exist"
print 'Sending File: ' + filePath
l = f.read(1024)
while (l):
print 'Sending...'
soc.send(l)
l = f.read(1024)
soc.send('end')
f.close()
print 'File sent'
except:
print "File does not exist"
the receiving code looks like this:
def receiveFile(self, ext, clientsoc):
f = open('receivedFile' + ext,'wb')
print "Receiving File..."
l = clientsoc.recv(1024)
while(l):
print "Receiving..."
if (l is not 'end'):
f.write(l)
print l + '\n'
l = clientsoc.recv(1024)
else:
break
f.close()
print "Received Fileeeeeooooo"
Even more strange, this code works when I am using it outside of my peer programme. Any help would be greatly appreciated, I have been struggling with this for two days now.
First of all, you must not compare strings with is or is not:
>>> a = "he"
>>> a + "llo" is "hello"
False
Second, TCP is a streaming protocol. recv is getting up to 1024 bytes, but could be less, and if you send two pieces from your server, they can be merged into one recv. So l is not likely to be "end" but "last bytes of the file's end". And if you check for "end", "end" is not allowed to be in the file. Best solution is to send the length of the file first, and then send and recv length bytes.
PS: you probably want to use sendall at the server side.
Sending the file size first worked!!
New code looks like this.
Sending code:
def sendFileOrImage(self,path):
name, ext = os.path.splitext(path)
filesize = str(os.path.getsize(path))
message = filesize + ',' + ext
print 'message'
for client in self.allClients.keys():
client.send(message)
self.sendFile(path)
def sendFile(self,filePath):
try:
f = open(filePath, 'rb')
except:
print "File does not exist"
print 'Sending File: ' + filePathty
for soc in self.allClients.keys():
l = f.read(1024)
while (l):
print 'Sending...'
soc.send(l)
l = f.read(1024)
f.close()
print 'File sent'
Receiving code:
def receiveFile(self,ext, filesize, clientsoc):
total = 0
f = open('receivedFile' + ext,'wb')
print "Receiving File..."
l = clientsoc.recv(1024)
total = len(l)
while(l):
print "Receiving..."
f.write(l)
if (str(total) != filesize):
print 'trying to receive'
l = clientsoc.recv(1024)
total = total + len(l)
else:
break
f.close()
print "Received Fileeeeeooooo"
Thanks everyone for the help!
Your receiving code works but still there is a problem you need to fix real quick. If your filesize is under 1024, your socket will keep listening for ever and in order to fix this problem you need to change your code like below.
def receiveFile(self,ext, filesize, clientsoc):
total = 0
f = open('receivedFile' + ext,'wb')
print("Receiving File...")
l = clientsoc.recv(1024)
total = len(l)
while(l):
print("Receiving...")
f.write(l)
if (str(total) != filesize):
print 'trying to receive'
l = clientsoc.recv(1024)
total = total + len(l)
if(int(total)>= int(filesize)):
break
f.close()
print("Received Fileeeeeoooo")

Categories