Python Передача файлов через socket
Пытаюсь сделать передачу файла через socket. Сам код работает и файлы передаются, НО когда я пытаюсь передать крупный файл (например картинку), данные отдаются один раз и потом все завершается. В итоге та же картинка просто обрывается сверху, так как данные не передались до конца. Как можно это решить? Я понимаю, что нужен цикл, но как его добавить - вообще не понимаю
Код сервера
import socket
s = socket.socket()
host = socket.gethostname()
port = 8080
s.bind((host, port))
s.listen(1)
print(host)
print("waiting...")
conn, addr = s.accept()
print(addr, "connected")
filename = input("enter filename: ")
file = open(filename, "rb")
file_data = file.read(4096)
conn.send(file_data)
print("file sended")
Код клиента:
import socket
s = socket.socket()
host = input("enter host address of sender: ")
port = 8080
s.connect((host, port))
print("connected")
filename = input("enter incoming filename: ")
file = open(filename, "wb")
file_data = s.recv(4096)
file.write(file_data)
file.close()
print("file downloaded")
Ответы (1 шт):
Файл передается кусочками в цикле, Вы передали только один кусочек. Для более взрослого кода на юниксоидах используйте sendfile - производительность больше в разы, а этот код исправляется так:
Код сервера
import socket
s = socket.socket()
host = socket.gethostname()
port = 8080
s.bind((host, port))
s.listen(1)
print(host)
print("waiting...")
conn, addr = s.accept()
print(addr, "connected")
filename = input("enter filename: ")
file = open(filename, "rb")
while True:
file_data = file.read(4096)
conn.send(file_data)
if not file_data:
break
conn.close()
print("file sended")
Код клиента:
import socket
s = socket.socket()
host = input("enter host address of sender: ")
port = 8080
s.connect((host, port))
print("connected")
filename = input("enter incoming filename: ")
file = open(filename, "wb")
while True:
file_data = s.recv(4096)
file.write(file_data)
if not file_data:
break
file.close()
print("file downloaded")
П.С. короткая запись
while file.write(s.recv(4096)): pass
sendfile на сервере, в виндовс выполнится через цикл с send, на юниксах через sendfile
conn.sendfile(file)
на клиенте нет функции на высоком уровне, оставь пока recv, но можно размер буфера побольше поставить. Разберусь с offset на низком уровне - допишу пример.