Клиент-серверное приложение на Python c использованием утилиты ffmpeg

Всем добрый день! столкнулся с проблемой: пишу клиент серверное приложение через sockets. Клиент и сервер могут чатиться текстовыми сообщениями. Теперь подключили утилиту ffmpeg, чтобы захватывать через запись с устройства клиента и передавать серверу аудиозапись в wav формате. Все работает ровно до того момента, как осуществляется передача файла. То есть при подключении клиента к серверу я спокойно могу чатиться, осуществлять запись и передавать. В момент того, как файл передался серверу, я больше не могу отправлять сообщения с клиента (с сервера все отправляется). Подозреваю, что проблема с потоками, при передачи файла не закрывается какой-то поток. Важно, чтобы после отправки файла, я также мог чатить клиент-сервер. Сервер на win, клиент на CentOS.
код клиента:

import socket, threading
import os
import struct
import argparse
from subprocess import Popen
from sys import argv

import os
import signal

import time

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


host = input('целевой IP-адрес входа')

while True:
    name = input('Пожалуйста, введите личный ник, не более десяти символов, менее одного символа')
    if 1 < len(name) < 10:
        break

port = 9090


client.connect((host, port))
print('-' * 5 + 'подключился к серверу' + '-' * 5)
print('-' * 5 + 'Enter, чтобы закрыть соединение с сервером' + '-' * 5)

def send_file_func():
    send_file(client, "records/output.wav")
    print('File has sent')


def outdatas():
    while True:


        outdata = input('')

        if outdata == 'enter':
            break

        client.send(f'{name}:{outdata}'.encode('UTF-8'))
        print('%s:%s' % (name, outdata))

proc = None
def record():
    global proc
    global pid
    output = " records/" + 'output.wav'
    cmdstr = "ffmpeg -f alsa -c:a pcm_s32le -sample_rate 44100 -i default:CARD=US16x08 -ac 4"  + output
    print(cmdstr)
    proc = Popen(cmdstr, shell=True)
    pid = proc.pid

def stop_record():
    global proc
    global pid
    output = " records/" + 'output.wav'
    cmdstr = "ffmpeg -f alsa -c:a pcm_s32le -sample_rate 44100 -i default:CARD=US16x08 -ac 4"  + output
    Popen.kill(proc)
    os.kill(pid,signal.SIGTERM)


def indatas():
    while True:

        indata = client.recv(1024)

        print(indata.decode('utf-8'))

        if ('Сервер:' and f'Начать запись, {name}') in indata.decode('utf-8'):
            client.send(f'{name}:Я начал запись'.encode('utf-8'))
            record()


        elif ('Сервер:' and f'Стоп, {name}') in indata.decode('utf-8'):
            stop_record()
            client.send(f'{name}:Я прислал файл'.encode('utf-8'))
            send_file_func()

def send_file(sck: socket.socket, filename):

    filesize = os.path.getsize(filename)

    sck.sendall(struct.pack("<Q", filesize))

    with open(filename, "rb") as f:

        while True:
            read_bytes = f.read(1024)
            if not read_bytes:
                break
            sck.sendall(read_bytes)

#lock = threading.RLock()

t1 = threading.Thread(target=indatas, name='input')

t2 = threading.Thread(target=outdatas, name='out')





t1.start()

t2.start()



t1.join()

#t2.join()




print('-' * 5 + 'сервер отключен' + '-' * 5)
client.close()

Код сервера:

# Импортировать пакет сокетов
import socket, threading
import struct
import os
# Создаем объект сокета
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Получить локальный ip
host = socket.gethostname()
s_ip = socket.gethostbyname(host)
print(s_ip)
# Данный порт
port = 9090

# Укажите IP и порт сервера
server.bind((host, port))

# Максимальное количество подключений
server.listen(5)

print('Enter Enter для выхода с сервера')

# Создайте список клиентов
clients = list()
# Хранить клиентов, которые создали потоки
end = list()


# Блокировка ожидания подключения клиента, возврата объекта подключения и адреса косвенного объекта
def accept():
    while True:
        client, addr = server.accept()
        clients.append(client)
        print("\ r" + '-' * 5 + f'сервер подключен через {addr}: текущее количество подключений: ----- {len (clients)}' + '-' * 5, end = '\n') #Взаимодействие с другими людьми


def recv_data(client):
    while True:
        
        # Принимаем информацию от клиента. Если приходит текст - печатаем его. Если файл, вызываем функцию receive_file
        # получаем сообщение вместе с файлом
        try:

            indata = client.recv(1024)
            if 'Я прислал файл' in indata.decode('utf-8'):
                
                # Ищем индекс символа : , затем определяем имя клиента, записываем в переменную name
                index = indata.decode('utf-8').find(':')
                name = indata.decode('utf-8')[:index]
                # Проверяем каталог на наличие папки, если нет - создаем, если есть, кладем файл в нужную папку
                if os.path.exists(name):
                    if os.path.isdir(name):
                        print('Папка существует')
                        filepath = name+'/'+'audio-received.wav'
                else:
                    print('Папка не существует')
                    os.mkdir(name)
                    filepath = name + '/' + 'audio-received.wav'
                # выполняем сохранение в нужном каталоге
                receive_file(client, filepath)
                print(indata.decode('utf-8'))
            else:
                print(indata.decode('utf-8'))

        except Exception as e:
            # если мы закрываем одного из клиентов, срабатывает блок except для того, чтобы не возникало
            # ошибок в процессе работы
            clients.remove(client)
            end.remove(client)
            print("\ r" + '-' * 5 + f'Сервер отключен: текущее количество подключений: ----- {len (clients)}' + '-' * 5, end = '\n')
            break

        finally:
            
            for clien in clients:
                # Перенаправить информацию от клиента и отправить ее другим клиентам
                if clien != client:
                    clien.send(indata)
                else:
                    continue


        #print('Файл получен')

def outdatas():
    while True:

        # Введите информацию, которая будет предоставлена клиенту
        print('')
        outdata = input('Введите сообщение своим пользователям\n')
        print()
        if outdata == 'enter':
            break
            print('Отправить всем:% s' % outdata)
            # Отправлять информацию каждому клиенту
        for client in clients:
            client.send(f"Сервер: {outdata}".encode('utf-8)'))

def indatas():
    while True:
        # Выполните цикл подключенных клиентов и создайте соответствующий поток
        for clien in clients:
            # Если поток уже существует, пропустить
            if clien in end:
                continue
           
            index = threading.Thread(target=recv_data, args=(clien,))
            index.start()
            
            end.append(clien)

def receive_file_size(sck: socket.socket):

    # Эта функция обеспечивает получение байтов,
    # указывающих на размер отправляемого файла,
    # который кодируется клиентом с помощью
    # struct.pack(), функции, которая генерирует
    # последовательность байтов, представляющих размер файла.
    fmt = "<Q"
    expected_bytes = struct.calcsize(fmt)
    received_bytes = 0
    stream = bytes()
    while received_bytes < expected_bytes:
        chunk = sck.recv(expected_bytes - received_bytes)
        stream += chunk
        received_bytes += len(chunk)
    filesize = struct.unpack(fmt, stream)[0]
    return filesize


def receive_file(sck: socket.socket, filename):
    # Сначала считываем из сокета количество
    # байтов, которые будут получены из файла.
    filesize = receive_file_size(sck)
    # Открываем новый файл для сохранения
    # полученных данных.
    with open(filename, "wb") as f:
        received_bytes = 0
        # Получаем данные из файла блоками по
        # 1024 байта до объема
        # общего количество байт, сообщенных клиентом.
        while received_bytes < filesize:
            chunk = sck.recv(1024)
            if chunk:
                f.write(chunk)
                received_bytes += len(chunk)
        print('Файл получен')


# Создать многопоточность
# Создать получающую информацию, объект потока

t1 = threading.Thread(target=indatas, name='input')
t1.start()

# Создать отправляемое сообщение, объект потока

t2 = threading.Thread(target=outdatas, name='out')
t2.start()

# Ожидание подключения клиента, объект потока

t3 = threading.Thread(target=accept(), name='accept')
t3.start()



# Блокировать округ, пока подпоток не будет завершен, и основной поток не может закончиться
t1.join()
#t2.join()


# Выключите все серверы
for client in clients:
    client.close()
print('-' * 5 + 'сервер отключен' + '-' * 5)

Ответы (0 шт):