2015-11-10 3 views
1

У меня действительно простой код, который позволяет мне отправлять изображение с клиента на сервер. И это работает.Отправка больших файлов в Twisted

Как просто:

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

def sendFile(self): 
     image = open(picname) 
     data = image.read() 
     self.transport.write(data) 

На стороне сервера ...

def dataReceived(self, data): 
     print 'Received' 
     f = open("image.png",'wb') 
     f.write(data) 
     f.close() 

Проблема с этим состоит в том, что работает только если изображение до 4.somethingkB, так как оно перестает работать, когда изображение больше (по крайней мере, не работает, когда доходит до 6kB). Тогда, когда я вижу, что «Получено» печатается более одного раза. Это заставляет меня думать, что данные разделяются на меньшие куски. Однако, даже если эти фрагменты данных попадают на сервер (поскольку я вижу повторяющуюся печать, вызванную из dataReceived), изображение повреждено и не может быть открыто.

Я не так много знаю о протоколах, но я полагал, что TCP должен быть надежным, поэтому факт, что пакеты попали туда в другом порядке или около того, не должен ... произойти? Поэтому я думал, что, возможно, Twisted делает что-то там, что я игнорирую, и, возможно, мне нужно использовать другой протокол.

Итак, вот мой вопрос. Есть ли что-то, что я мог бы сделать сейчас, чтобы заставить его работать, или я обязательно должен перейти к другому протоколу? Если да ... любая идея? Моя цель - отправить более крупное изображение, возможно, порядка сотен kB.

+1

Вам необходимо отправить его в виде блоков. Храните файл открытым в конце приема и записывайте каждый блок по мере его поступления. Он может поступать в блоки разного размера. –

+0

Чтобы отправить его в блоки, вы можете использовать протокол FileSender (http://twistedmatrix.com/documents/15.4.0/api/twisted.protocols.basic.FileSender.html) \t filesender = basic.FileSender() \t filesender.beginFileTransfer (данные, self.транспорт) –

ответ

1

Это вариант записи в рассеченной FAQ:

TCP является потока на основе протокола. Он доставляет поток из байтов, которые могут быть разбиты на произвольное число фрагментов. Если вы пишете один большой блок байтов, он может быть разбит на произвольное количество меньших фрагментов, в зависимости от характеристик вашего физического сетевого подключения. Когда вы говорите, что TCP должен быть «надежным» и что куски должны поступать по порядку, вы грубо верны: однако, что приходит в порядок, это байтов, а не куски.

Что вы делаете в вашем методе dataReceived есть, при получении каждого фрагмента, открытие файла и записи содержимого только тот кусок к "image.png", а затем закрыть его. Если вы измените его, чтобы открыть файл в connectionMade и закройте файл в connectionLost, вы должны увидеть хотя бы неопределенное правильное поведение, хотя это все равно приведет к повреждению/усечению изображений, если соединение будет неожиданно потеряно, без предупреждения. Вы действительно должны использовать протокол кадрирования, такой как AMP; хотя, если вы просто отправляете большие капли данных, HTTP, вероятно, лучший выбор.

+0

Эй, @ Глиф, спасибо за ответ. Я попробовал метод connectMade - 'connectionLost', и он работал хорошо, хотя ... думаю, что если я хочу надежную структуру, я не должен ее использовать. Я хотел бы объединить эту функцию с большим проектом, который у меня есть, который использует протокол TCP, поэтому, если бы я мог избежать изменения всего этого кода, было бы замечательно. Было бы отправить его в блоки, как, например, @MartinEvans, хороший вариант здесь? Или это все равно будет противоречить какому-то внутреннему механизму Twisted? Еще раз спасибо! – josepmeg

+0

@josepmeg - звучит так, как будто вы должны задать другой вопрос - заполнить весь ответ в поле комментариев здесь будет непросто :). Когда вы спросите нового, обязательно заполните то, что ваши требования и почему они так, потому что я не уверен, что полностью понимаю, что такое «весь этот код». – Glyph