Python передать изображение через socket

Передача файла через сокет в Python 3

Язык программирования Python

Следующий код устанавливает соединение клиент-сервер между двумя программами Python с помощью стандартного модуля socket и отправляет файл с клиента на сервер.

Логика передачи файлов содержится в двух функциях: клиент определяет функцию send_file() для отправки файла через сокет и, наоборот, сервер определяет функцию receive_file() для его получения.

Таким образом, вы сможете легко перенести функции из этой статьи в другие программы, которые уже реализуют соединение клиент-сервер.

Код подготовлен для отправки файлов любого формата и любого размера. Требуется Python 3.8 или выше.

Сервер:

# server.py import socket import struct def receive_file_size(sck: socket.socket): # Эта функция обеспечивает получение байтов, # указывающих на размер отправляемого файла, # который кодируется клиентом с помощью # struct.pack(), функции, которая генерирует # последовательность байтов, представляющих размер файла. fmt = " 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) with socket.create_server(("localhost", 6190)) as server: print("Ожидание клиента. ") conn, address = server.accept() print(f": подключен.") print("Получаем файл. ") receive_file(conn, "image-received.png") print("Файл получен.") print("Соединение закрыто.")
Code language: PHP (php)

Клиент

# client.py import os import socket import struct def send_file(sck: socket.socket, filename): # Получение размера файла. filesize = os.path.getsize(filename) # В первую очередь сообщим серверу, # сколько байт будет отправлено. sck.sendall(struct.pack(", filesize)) # Отправка файла блоками по 1024 байта. with open(filename, "rb") as f: while read_bytes := f.read(1024): sck.sendall(read_bytes) with socket.create_connection(("localhost", 6190)) as conn: print("Подключение к серверу.") print("Передача файла. ") send_file(conn, "image.png") print("Отправлено.") print("Соединение закрыто.")
Code language: PHP (php)

Чтобы протестировать код, вы должны изменить вызовы send_file() и receive_file(), указав путь к файлу, который вы хотите отправить, и путь к файлу, в котором вы хотите его получить.

В текущем коде это файл image.png, который находится в той же папке, что и два файла Python, и принимается как image-received.png.

После этого запустите сервер:

python server.py
Code language: CSS (css)

Затем, на другом терминале, клиент:

python client.py
Code language: CSS (css)

Вывод сервера будет выглядеть следующим образом:

Ожидание клиента. 127.0.0.1:60331 подключен. Получаем файл. Файл получен. Соединение закрыто.
Code language: CSS (css)
Подключение к серверу. Передача файла. Отправлено. Соединение закрыто.

Источник

Русские Блоги

Python использует сокет для передачи изображений, видео и других файлов

При разработке некоторых приложений, требующих сетевой связи, для связи часто используются различные сетевые протоколы. При разработке робота в лаборатории блогер столкнулся с необходимостью отправлять изображения, собранные на роботе, обратно на сервер для обработки и идентификации. Реализация под python следующая (размещен только ключевой код)

Сервис-Терминал

LOCAL_IP = '192.168.100.22' # Адрес этой машины в локальной сети, или пишем 127.0.0.1 PORT = 2567 # Укажите порт def server(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # socket.AF_INET относится к ipv4 socket.SOCK_STREAM с использованием протокола tcp sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Установить порт sock.bind((LOCAL_IP, PORT)) # Привязка порта sock.listen(3) # Прослушивание порта while True: sc,sc_name = sock.accept() # Когда есть запрос на указанный порт, accpte () вернет новый сокет и хост (ip, порт) print("Получен <> запрос".format(sc_name)) infor = sc.recv(1024) # Сначала получите фрагмент данных, этот фрагмент данных содержит длину файла и имя файла, разделенные знаком |, конкретные правила могут быть указаны на клиенте length,file_name = infor.decode().split('|') if length and file_name: newfile = open('image/'+str(random.randint(1,10000))+'.jpg','wb') # Здесь можно использовать имя файла, полученное от клиента print('length <>,filename <>'.format(length,file_name)) sc.send(b'ok') # Указывает длину полученного файла и имя файла file = b'' total = int(length) get = 0 while get  total: # Получать файлы data = sc.recv(1024) file += data get = get + len(data) print('Должен получить <>, фактически получить <>'.format(length,len(file))) if file: print('acturally length:<>'.format(len(file))) newfile.write(file[:]) newfile.close() sc.send(b'copy') # Расскажи полный полученный файл sc.close() 

Клиент

address = ('192.168.100.22', 2567) def send(photos): for photo in photos[0]: print('sending <>'.format(photo)) data = file_deal(photo) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(address) sock.send('<>|<>'.format(len(data), file).encode()) # Кодировка по умолчанию utf-8, длина отправляемого файла и имя файла reply = sock.recv(1024) if 'ok' == reply.decode(): # Подтвердите, что сервер получает данные о длине и имени файла go = 0 total = len(data) while go  total: #Послать файл data_to_send = data[go:go + 1024] sock.send(data_to_send) go += len(data_to_send) reply = sock.recv(1024) if 'copy' == reply.decode(): print('<> send successfully'.format(photo)) sock.close() # Поскольку tcp передает данные в виде потока, мы не можем определить начало и конец. Самый простой способ - использовать сокет без передачи файла, но это потребляет ресурсы компьютера. Блоггеры ищут более эффективные методы. Возможность общаться def file_deal(file_path): # Метод чтения файла mes = b'' try: file = open(file_path,'rb') mes = file.read() except: print('error<>'.format(file_path)) else: file.close() return mes 

Источник

Блог

Как правильно отправить изображение через сокет с помощью клиента python и сервера C

#python #c #linux #sockets

#python #c #linux #сокеты

Вопрос:

Я программирую приложение, похожее на чат, в котором пользователь, помимо отправки сообщений, может также отправлять фотографии. Единственная проблема заключается в том, что я не уверен, как мне следует подходить к отправке изображений. Основная идея заключается в том, что пользователь выбирает запись изображения /send image.jpg в консоли, а затем изображение отправляется через socket.send(image.jpg) . Отправка изображения для меня работает нормально, но мой сервер C получает данные от клиента в отдельных «пакетах» из-за буфера, но когда я добавляю их, они не соответствуют размеру моего изображения (например, мое изображение составляет 73 КБ, но сервер получает 29 КБ из двух отдельных «пакетов» 20 КБ 8,5кб). И вторая проблема заключается в том, как отправить эти данные дальше, я подумал, что, возможно, есть какой-то способ передать buffor с фактическими двоичными данными изображения и отправить их остальным моим клиентам на Python. Мой буфер составляет 20480 байт.

 elif "/send " in buffer: fileArr = buffer.split(' ') #filearr = ["/send", "image.jpg"] file = open(fileArr[1], "rb").read() s.send(fileArr[0].encode()) #metadata that im sending image file time.sleep(0.2) s.send(file) #sending my file time.sleep(1) print("Image sent!") 

Мой сервер.c получением и отправкой:

 void send_message(char *s, int uid)< pthread_mutex_lock(amp;clients_mutex); for (size_t i = 0; i < MAX_CLIENTS; i ) < if(clients[i])< if(clients[i]-> uid != uid)< if(write(clients[i]->sockfd, s, strlen(s)) < 0)< perror(""); printf("Write to descriptor failed n"); break; > > > > pthread_mutex_unlock(amp;clients_mutex); > if(strstr(buffer, "/send") != NULL || receive > 128)< if(strstr(buffer, "/send"))< buffer[0] = ''; > recv(cli->sockfd, buffer, sizeof(buffer), 0); // Receiving my image and saving it to buffer printf("receiveing img"); send_message(buffer, cli->uid); // Sending my buffer further to client printf("sending imagen" ); 
 def recvDataLoop(): while True: reply = s.recv(buffer_sz) if reply: print("Got reply"); flag = 0 try: reply = reply.decode() if flag != 1 and "joined the chat" in reply or "has left" in reply: print(reply) elif flag != 1 and "|" in reply: replyArr = reply.split("|") time.sleep(0.1) print("<>: <>".format(replyArr[0],replyArr[1])) except: print("Encoded") #If data received and it cannot be decoded, its try: f = open("cat4.jpg", "ab").write(reply) #If image exists, write data to existing image except: f = open("cat4.jpg", "wb").write(reply) 

Мне нужно было выполнить эту попытку, кроме блоков, потому что, когда данные получены, они поступают в пакетах, поэтому, когда я их получаю, мне нужно записать их в конец моего cat4.jpg досье.

Комментарии:

1. Не связано: send_message похоже, что он может удерживать мьютекс заблокированным в течение неудобно долгого времени.

2. Никогда не игнорируйте коды возврата из, ну, что угодно, но вы не можете игнорировать их в программировании сокетов. Например, recv код возврата сообщает вам, сколько данных было прочитано. Это важная информация, потому что вы никогда не знаете, сколько данных вы собираетесь получить.

3. Код сокета, «изображение» и «strlen» в том же сообщении:((

4. Как вы определяете, являются ли полученные данные текстовым сообщением или двоичными данными изображения? Вам следует рассмотреть возможность создания более надежного пользовательского протокола, который отправляет значение в первом байте, указывающее, как обрабатывать остальные данные. Вы также должны быть осторожны с нулевыми байтами. Байт со значением 0x00 в строковых данных означает конец строки, тогда как тот же байт в данных изображения представляет собой просто черный пиксель.

Ответ №1:

Функции rx / tx сокета обычно возвращают фактическое количество переданных байтов. Таким образом, правильный способ выполнения rx / tx — вызвать функцию в цикле, одновременно накапливая возвращаемое значение и перемещая указатель начала буфера. Более того, при работе с двоичными данными, такими как данные изображения, предположение о нулевом завершении неверно и усекает данные неправильной длины; это также может вызвать исключения, связанные с индексом массива, выходящим за пределы. Вам необходимо явно указать количество байтов rx / tx ( strlen неверно).

Источник

Python-сообщество

[RSS Feed]

  • Начало
  • » Network
  • » Передача изображения через сокеты.

#1 Май 30, 2012 11:27:40

Передача изображения через сокеты.

Делаю простой webserver. Вопрос как через сокеты передать изображение?

#2 Май 30, 2012 11:35:44

Передача изображения через сокеты.

Google: ‘send image over socket python’. В первых 10 ссылках 8 ответов на ваш вопрос.

#3 Июнь 2, 2012 11:19:59

Передача изображения через сокеты.

Там написано, что надо открывать изображение как текст и передавать текст. Если так делать, то клиент не может открыть изображение.
К тому же мне нужно уметь передавать не только изображение, но и другие файлы(музыку, видео).

#4 Июнь 2, 2012 14:10:58

Передача изображения через сокеты.

Если вы думаете, что передача изображения отличается чем-то от передачи видеоролика, музыки или комиксов, то вы ошибаетесь. Вы передаёте байты, другое дело — интерпретация их значения на стороне клиента.

#5 Июнь 3, 2012 09:10:36

Передача изображения через сокеты.

как текст его открывать нельзя
нужно открыть файл изображения в двоичном режиме
потом читать его через .read() и эти байты передавать в сокет

Отредактировано py.user.next (Июнь 3, 2012 09:12:52)

#6 Июнь 3, 2012 12:20:56

Передача изображения через сокеты.

fata1ex
Если вы думаете, что передача изображения отличается чем-то от передачи видеоролика, музыки или комиксов, то вы ошибаетесь. Вы передаёте байты, другое дело — интерпретация их значения на стороне клиента.

#7 Июль 16, 2012 05:16:23

Передача изображения через сокеты.

fata1ex
Если вы думаете, что передача изображения отличается чем-то от передачи видеоролика, музыки или комиксов, то вы ошибаетесь. Вы передаёте байты, другое дело — интерпретация их значения на стороне клиента.

В том-то и дело, что на клиенте интерпретировать не удается.
а http заголовки передаете? как без них клиент будет интерпретировать контент?

Источник

Читайте также:  Эффективная отдача файлов php
Оцените статью