2015-12-06 3 views
2

Я пишу параллельный TCP-сервер (процесс на основе параллелизма), который принимает команду загрузки. Клиент должен загрузить файл с сервера, так как прямо сейчас у меня есть имя файла, жестко запрограммированное для загрузки, чтобы проверить мой алгоритм загрузки.Загрузка файла в python с использованием сокетов TCP

Я искал образец download algorithm и использую цикл while, используемый в этом коде.

Я думаю, что моя проблема в том, что одна из циклов while (или, возможно, их обоих) получает повесил трубку и не закончится. Я считаю, что Это клиентская сторона, и это, скорее всего, ждет больше fileContent.

сервер

  file = open('download.txt','rb+') 
      print "Opened File: " , file.name 

      fileContent = file.read(1) 
      clientsocket.send(fileContent) 
      while (fileContent): 
       print "iteration", fileContent 
       clientsocket.send(fileContent) 
       fileContent = file.read(1)     
      file.close() 

сторона клиента

print "Attempting download..." 
    f = open('downloaded.txt' , 'wb+')  
    print "Opened File: " , f.name 
    fileContent = s.recv(1) 
    while (fileContent): 
     print "iteration", fileContent 
     f.write(fileContent) 
     fileContent = s.recv(1) 
    print "Download Complete" 
    f.close() 

Я выполнил передачу файлов без времени цикла, используя код, такой как

f.open(file) 
fContent = f.read(1024) 
client.send(fContent) 
f.close 

f.open(file) 
fContent = server.recv(1024) 
f.write(fContent) 
f.close 

, но я знаю, что это вызывает проблемы если размер файла больше размера буфера.

Это параллельный сервер, который использует отдельный процесс для обработки каждого соединения. (Я не считаю, что это должно повлиять на мою текущую проблему, но я новичок в параллелизме и подумал, что я упоминал об этом.)

Кто-нибудь знает, почему мои циклы while не заканчиваются? Или кто-нибудь знает что-то еще, что я могу сделать неправильно? Заранее спасибо!

редактировать:

Мой выход:

кли

Attempting download... 
Opened File: downloaded.txt 
iteration t 
iteration h 
iteration i 
iteration s 
iteration 
iteration i 
iteration s 
iteration 
iteration a 
iteration 
iteration f 
iteration i 
iteration l 
iteration e 
iteration 

серв

Recived dl from: ('127.0.0.1', 38161) | 2015-12-06 13:07:12.835998 
Opened File: download.txt 
iteration t 
iteration h 
iteration i 
iteration s 
iteration 
iteration i 
iteration s 
iteration 
iteration a 
iteration 
iteration f 
iteration i 
iteration l 
iteration e 
iteration 

клиент застревает, и я чтрл г его. Сервер будет продолжать принимать соединения. Я просто понял, что я могу добавить простой оператор печати после цикла while сервера, чтобы проверить, завершен ли цикл while сервера.

второй править:

Сервер не получает повесил трубку (он успешно выводит сообщение после цикла). Это заставляет меня думать, что клиент вызывает recv() и ждет больше fileContent.

третье редактирование:

Буфер чтения/записи только в 1 для целей тестирования.

+0

На стороне сервера, вы не закрыть сокет, так что клиент не знает файл закончился. Добавьте 'clientsocket.shutdown (socket.SOCK_RDWR)', а затем 'clientsocket.close()'. – tdelaney

+0

@tdelaney Сервер должен продолжать принимать команды.Я не хочу, чтобы соединение завершилось после завершения загрузки, не произойдет ли это, если я закрою сокет? – Greg

+1

Да, это закончилось бы. Но если вы хотите сохранить сокет открытым, у вас есть большая проблема, потому что вам все еще нужен способ сообщить клиенту, что передача завершена. Общим способом сделать это является использование модуля 'struct' для определения структуры сообщений (скажем, поля флагов, чтобы сказать, является ли это последним фрагментом плюс длина), за которым следует точно длина байтов из файла. Клиент будет читать заголовок, а затем читать точно длины байтов и повторять до тех пор, пока флаги не остановятся. – tdelaney

ответ

1

Отправка файла байтом по байтам может быть очень медленной. Лучшее использование shutil.copyfileobj, который обрабатывает передачу для вас:

def send_file(socket, filename): 
    with open('download.txt','rb') as inp: 
     print "Opened File: " , file.name 
     out = socket.makefile('wb') 
     shutil.copyfileobj(inp, out) 

def recv_file(socket, filename): 
    with open('download.txt','wb') as out: 
     print "Opened File: " , file.name 
     inp = socket.makefile('rb') 
     shutil.copyfileobj(inp, out) 
+1

Это гораздо полезнее, чем то, что я пытаюсь сделать, однако я бы хотел сделать это выше. Это для школьного проекта, и я стараюсь подражать «c», насколько могу, и я не верю, что «c» имеет этот вызов :( – Greg

Смежные вопросы