Передача нескольких файлов Python через сокеты TCP

Я пытаюсь написать программу на python для передачи нескольких файлов в папке через сокет, пока у меня есть следующий код

Клиент:

def uploadFiles(folder,dcip,PORT,filetype):
    os.chdir(folder)
    dirList = os.listdir(folder)
    print dirList
    ms = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print PORT
    ms.connect((dcip, int(PORT)))
    for fname in dirList:

        if fname.endswith(str(filetype)):
            cmd = 'get\n%s\n' % (fname)
            ms.sendall(cmd)
            f = open(fname,'rb')
            data = f.read()
            f.close()
            print data
            r = ms.recv(2)
            ms.sendall(data)
            ms.sendall('done\n%s\n' %(fname))
    ms.sendall('end\n\n')   
    ms.close()

Сервер:

import socket,os
listener_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listener_socket.bind(('',33234))
filename = ''
while 1:
    listener_socket.listen(100)
    connection,address_client = listener_socket.accept()
    if not os.path.exists(str(address_client[0])):
        os.makedirs(str(address_client[0]))
    currdir = os.getcwd()
    os.chdir('./'+str(address_client[0]))

    while(1):
        data = connection.recv(4096)
        cmd = data[:data.find('\n')]

        if cmd == 'get':
            x,filename,x = data.split('\n',2)
            connection.sendall('ok')
            f = open(filename,'wb')


        if cmd == 'done':
            continue

        f.write(data)

        if cmd == 'end':
            connection.close()
            break
    os.chdir(currdir)

Приведенный выше код переходит в бесконечный цикл, и я понимаю, что это из-за оператора continue в части if cmd == 'done', интересно, почему он это делает? Я имею в виду, что он никогда не получает готовое сообщение от клиента, может ли кто-нибудь помочь мне исправить код?


person srnvs    schedule 07.02.2013    source источник
comment
Ваш цикл завершится сообщением «конец», а не сообщением «готово».   -  person James Thiele    schedule 08.02.2013
comment
Я отправляю сообщение о завершении после передачи всех файлов. Кроме того, он не копирует файлы как есть, он зацикливается на самом первом файле.   -  person srnvs    schedule 08.02.2013
comment
Поскольку чтение выполняется блоками, только первая команда будет в начале блока. Другие команды (get, done, end) будут находиться где-то внутри того же или следующего блока(ов). Следует сделать более грамотный разбор полученных данных.   -  person Ante    schedule 08.02.2013


Ответы (1)


Поскольку команды и имена файлов находятся в отдельных строках, лучше всего анализировать полученные данные по строкам. Последняя часть данных блока не обязательно должна заканчиваться \n, поэтому она должна быть объединена со следующим полученным блоком данных.

Это (не проверенная) реализация разбора полученных данных по строкам:

data = '' # contains last line of a read block if it didn't finish with \n
in_get, in_done, reading_file, ended = False, False, False, False
while not ended:
  if len(data) > 100:  # < update
    f.write( data )    # <
    data = ''          # <
  data += connection.recv(4096)
  i = data.find('\n')
  while i >= 0 and not ended:
    line = data[:i]
    data = data[i+1:]
    if in_get:
      filename = line
      reading_file = True
      f = open(filename,'wb')
      in_get = False
    elif in_done:
      if line != filename:  # done inside file content
        f.write( 'done\n' + line + '\n' )
      else:
        f.close()
        reading_file = False
      in_done = False
    else:
      if line == 'get' and not reading_file:
        in_get = True
      elif line == 'done':
        in_done = True
      elif line == 'end' and not reading_file:
        ended = True
        break;
      else:
        f.write( line + '\n' )
    i = data.find('\n')
person Ante    schedule 08.02.2013
comment
Анте, я внес необходимые изменения, и он отлично работает для файлов меньшего размера, но я пытаюсь передать файлы большего размера (текстовые файлы 256 КБ, все случайные числа без новых строк), он не распознает новые строки между файлами, он просто записывает все в один большой файл и переходит в бесконечный цикл, можете ли вы сказать мне, где это может пойти не так, особенно для больших файлов? - person srnvs; 12.02.2013
comment
Я не знаю :-) Команды и имена файлов "короткие", так что может помочь исправить запись данных в файл, если данные слишком длинные. Я изменю верхний код с этим исправлением. - person Ante; 12.02.2013