I suggest that you use json
or pickle , although with json the serialization can be faster .
That said, this question inadvertently becomes a bit nabragente / defiant.
The error description itself speaks in the problem, that is, you need to send bytes and not a tuple, and since you can not convert a tuple
into bytes directly but can do it with strings, you can send a json in this case becomes more laborious and so I will not do this, I explain below the reason).
However, we still have a problem, you can not send the bytes of the file in json because serialization problems occur ( list of data types that json understands ), you would have to send two separate messages , one with (name, file size etc .., in the form of a dict for example) and another with the bytes that compose it, and VERY IMPORTANT, you would have to send a flag (byte null eg, b'\x00'
) in the end of the first one to indicate that it has reached the end and that the server can then start receiving the binary data from the file.
This flag must exist because TCP is a streaming protocol there is no guarantee that the recv
(server side in this case) method received exactly the json with the information before, it may contain only a part of the json or it may include some of the binary file information to the mix. p>
Here I put a basic example of upoload of files to the server with pickle, where we can convert a data structure (objects, dictionaries, tuples, etc ...) into a
byte stream , so with pickle, we can send the required data " time ", so in this case it facilitates a lot:
Client:
import socket, pickle
f = input('escreva o nome do ficheiro')
f_bin = open(f, 'rb').read()
info = {'name': f, 'file': f_bin, 'opcao': 1} # ajustar opcao para adequar ao teu codigo
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(('', 9005))
s.sendall(pickle.dumps(info))
Server:
import socket, threading, pickle, time
def run(conn):
info_bin = b''
st = time.time()
while True:
c = conn.recv(2048)
if not c:
break
info_bin += c
if time.time() - st >= 2: # opcional, informacao sobre o total ja carregado
print('bytes downloaded:', len(info_bin))
st = time.time()
info = pickle.loads(info_bin)
if info['file']:
dest = 'files/{}'.format(info['name'])
with open(dest, 'wb') as f:
f.write(info['file'])
print('success on receiving and saving {} for {}'.format(info['name'], conn.getpeername()))
conn.close()
host, port = ('', 9005)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((host, port))
sock.listen(5)
while True:
conn, addr = sock.accept()
print('conn', addr)
threading.Thread(target=run, args=(conn,)).start()
I have not tested with multiple clients but in principle it will also work.
You need to adjust your connection and the site where the server will write the file