Отправка файла png через сокет в Python

Я использую Python версии 2.7.9 и пытаюсь отправить файл png. Но происходит что-то странное... я использую сокеты и отправляю почтовый запрос (или вроде того). Я отправляю запрос на сервер от клиента, затем я печатаю длину запроса, полученного на сервере, например, длина: 1051.

Затем я делаю регулярное выражение, чтобы взять данные файла png, а затем печатает длину, а длина составляет 2632, что он больше, чем ответ?!

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

Исходный код сервера:

import socket
import re

server = socket.socket()
server.bind(('0.0.0.0',8080))

while True:
    server.listen(2)
    (client, client_addr) = server.accept()
    print 'IP :',client_addr

    res = client.recv(0xfffffff)
    print len(res)

    #get file name
    file_name = res.split('&')[0]
    file_name = str(file_name.split('=')[1])
    print repr(res)

    #get the data of the file
    raw_img = str(re.findall("&photo_data=(.*)" ,res ,re.DOTALL))

    print "File name:" + file_name
    print "Size:" + str(len(raw_img))
    with open(file_name, 'wb') as f:
        f.write(raw_img)

    print "Done"

Исходный код клиента:

import socket

client = socket.socket()
client.connect(('127.0.0.1',8080))

raw_data = open('test.png', 'rb').read()
save_file_name = raw_input("Enter the file name:")
print len(raw_data)

output = 'POST /upload HTTP/1.1\r\n'
output += 'Content-Length:' + str(len(raw_data)) + str(len(save_file_name)) + '\r\n\r\n'
output += 'file_name=' + save_file_name + '&'
output += 'photo_data=' + raw_data
print len(output)

client.send(output)
client.close()

person null    schedule 30.04.2015    source источник
comment
Вопрос в том, почему вы используете необработанные сокеты? Есть библиотеки, которые позаботятся об этом за вас. Тем более, что вы, похоже, приняли формат отдыха, вы можете просто использовать бутылку в качестве сервера отдыха и запросы в качестве клиента.   -  person Tymoteusz Paul    schedule 01.05.2015
comment
Это часть обучающих сетей, поэтому на данный момент я не использую готовые библиотеки.   -  person null    schedule 01.05.2015
comment
Вы говорите, что сервер получает меньше данных, чем ожидалось? В отличие от файла, сокет возвращает меньшие фрагменты данных, поэтому res = client.recv(0xfffffff) может не быть полным png. Продолжайте читать сокет в цикле, пока он не вернет строку нулевой длины.   -  person tdelaney    schedule 01.05.2015
comment
Нет, но после фильтрации данных становится больше.   -  person null    schedule 01.05.2015


Ответы (1)


Во-первых, вы должны использовать while True для получения полных данных:

res = ''
while True:
    data = client.recv(1024)
    if not data:
        break
    res += data
print len(res)

Тогда re.findall фактически возвращает массив, а не строку. Итак, вы должны сделать это:

r = re.findall("&photo_data=(.*)" ,res ,re.DOTALL)
raw_img = str(r[0])

Теперь он работает нормально.


Почему не работает код перед? Допустим, у нас есть список:

r = ['\x45']

Данные в части raw_img в основном такие. Если мы грубо преобразуем этот список в строку, мы получим:

print len(str[r]))  # ['E'], 5

На самом деле нам нужно r[0]:

print len(str[r[0])) # 1

Поэтому размер файла стал больше.

person skyline75489    schedule 01.05.2015