Не выходит из цикла после получения всех нужных данных

Пишу программу, которая после подключения просит у пользователя ввести "команду". После введения "команды"/"аргумента" клиентская часть кода создает архив файлов, после чего пересылает их в серверную часть, куда эти файлы и должны прийти. После, в серверной части, уже по считыванию "команды" создается архив на сохранение и происходит цикл, пока все данные не будут получены. Данные(байты) будут считываться и сохраняться, но после того как все данные получены, выход из цикла не происходит. Причем в клиентской части с циклом все ОК. Сам я не профи в программировании и перепробовал все возможные способы, но ничего не получилось. Если кто-то поможет решить данную проблему, буду благодарен.

СЕРВЕРНЫЙ КОД

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 шт):

Автор решения: Stanislav Volodarskiy

Если в сокете данных нет, 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}')

Сессия:

Клиент Сервер



$ python client.py
connecting...
waiting for command...
received command: 1
sending...
sent 770306

$
$ python server.py
> 1
waiting for client...


connection accepted

receiving...
received 770306

>
→ Ссылка