Here a minimal implementation. I have done it to wake up.
Later i realized that my variable name for received was wrong..
server.py
import socket
import os
import struct
import hashlib
def handle(client, addr):
buffsize = 1024
file = '/home/deadeye/foster_the_people_20110408_128.mp3'
print('File size:', os.path.getsize(file))
fsize = struct.pack('!I', os.path.getsize(file))
print('Len of file size struct:', len(fsize))
client.send(fsize)
with open(file, 'rb') as fd:
while True:
chunk = fd.read(buffsize)
if not chunk:
break
client.send(chunk)
fd.seek(0)
hash = hashlib.sha512()
while True:
chunk = fd.read(buffsize)
if not chunk:
break
hash.update(chunk)
client.send(hash.digest())
client.close()
addr = ('', 8080)
sock = socket.socket()
sock.bind(addr)
sock.listen(5)
# while True loop normally
# to handle incomming connections
client, addr = sock.accept()
print('Got connection from:', addr)
handle(client, addr)
sock.close()
client.py
mport socket
import os
import struct
import hashlib
addr = ('localhost', 8080)
sock = socket.socket()
sock.connect(addr)
print('Connected to', addr)
received = 0
chunks = []
while received< 4:
data = sock.recv(4 - received)
received += len(data)
chunks.append(data)
print('Received len of file size struct', len(b''.join(chunks)))
fsize = struct.unpack('!I', b''.join(chunks))[0]
print('Filesize:', fsize)
buffer = 1024
received = 0
chunks = []
while received < fsize:
data = sock.recv(min(fsize - received, buffer))
received += len(data)
chunks.append(data)
file = b''.join(chunks)
print('Received file')
print('Expected size:', fsize)
print('Received size:', len(file))
received = 0
chunks = []
while received < 64:
data = sock.recv(64 - received)
received += len(data)
chunks.append(data)
sha512 = b''.join(chunks)
print('Received Hash', len(sha512), sha512)
sock.close()
hash_ok = hashlib.sha512(file).digest() == sha512
print('Hash is ok') if hash_ok else print('Hash is not ok')
The problem with sockets are, that the call recv(size) does not guarantee that you really receiving this given data size. So you have to send the file size you want to send. With struct.pack and struct.unpack you can send the given file size. Afterwards I'm sending a hash, to check if the transfer was really right.
I did not any optimization. On client side you can write the data to disk instead of appending the chunks into a list. The check afterwards can be done with the same procedure as shown on server side. But this is optional to check the data integrity.
If you want to have the song, write a PN :-D