Не выходит из цикла после получения всех нужных данных
Пишу программу, которая после подключения просит у пользователя ввести "команду". После введения "команды"/"аргумента" клиентская часть кода создает архив файлов, после чего пересылает их в серверную часть, куда эти файлы и должны прийти. После, в серверной части, уже по считыванию "команды" создается архив на сохранение и происходит цикл, пока все данные не будут получены. Данные(байты) будут считываться и сохраняться, но после того как все данные получены, выход из цикла не происходит. Причем в клиентской части с циклом все ОК. Сам я не профи в программировании и перепробовал все возможные способы, но ничего не получилось. Если кто-то поможет решить данную проблему, буду благодарен.
СЕРВЕРНЫЙ КОД
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("localhost", 12345))
s.listen()
conn, addr = s.accept()
print("SUCCESSFULLY")
while True:
cmd = input("> ")
if cmd[:1] == "1":
conn.send(cmd.encode())
data = conn.recv(8192)
file=open('1_ser.zip', mode="wb")
while data:
print(data)
if not data:
break
else:
file.write(data)
data = conn.recv(8192)
file.close()
print(f"ВЫХОД СОВЕРШЕН ИЗ СЕРВЕРА!")
КЛИЕНТСКИЙ КОД
import socket, zipfile, os
from zipfile import ZipFile
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 12345))
while True:
cmd = s.recv(8192)
cmd = cmd.decode()
if cmd[:1] == "1":
ziph = ZipFile(f'{cmd[2:]}\\1.zip', 'w', compression=zipfile.ZIP_DEFLATED, compresslevel=1)
for root, dirs, files in os.walk(f"{cmd[2:].strip()}"):
for file in files:
ziph.write(os.path.join(root, file))
ziph.close()
#Пример: "1 C:\Users"
# без кавычек и \ в самом конце пути
file = open(f'{cmd[2:]}\\1.zip', mode="rb")
data = file.read(8192)
while (data):
s.send(data)
data = file.read(8192)
print(f"ВЫХОД СОВЕРШЕН ИЗ КЛИЕНТА!")
file.close()
Ответы (1 шт):
Если в сокете данных нет, conn.recv(8192) остановится и будет их ждать. Чтобы он не ждал, клиент должен закрыть сокет со своей стороны. Как только это произойдёт, conn.recv вернёт пустую data и цикл на сервере завершится.
Если вы не хотите закрывать сокет, вам придётся изобрести "маркер конца данных" и обязать клиент передавать его после передачи самих данных. Но это сложно, лучше открывать/закрывать сокет.
Сервер:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 12345))
s.listen()
while True:
cmd = input('> ')
print('waiting for client...')
conn, addr = s.accept()
print('connection accepted')
conn.send(cmd.encode())
print('receiving...')
buf = []
while part := conn.recv(8192):
buf.append(part)
data = b''.join(buf).decode()
conn.close()
print(f'received {len(data)}')
Клиент:
import socket
import random
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('connecting...')
s.connect(('localhost', 12345))
print('waiting for command...')
cmd = s.recv(8192)
cmd = cmd.decode()
print(f'received command: {cmd}')
n = random.randint(10 ** 4, 10 ** 5)
print('sending...')
size = 0
for i in range(n):
line = f'{i}: {cmd}\n'
size += len(line)
s.send(line.encode())
s.close()
print(f'sent {size}')
Сессия:
| Клиент | Сервер |
|---|---|
|
|