Отправка изображения через сокеты (ТОЛЬКО) в Python, изображение не может быть открыто
Я хочу загрузить изображение с клиента на сервер, используя ТОЛЬКО сокеты в Python. Я разработал очень простой поток протокола, как я хотел бы сделать это:
CLIENT SERVER
SIZE 512 (send image size)
---------------------------------->
GOT SIZE
<----------------------------------
send image itself
---------------------------------->
GOT IMAGE
<----------------------------------
BYE BYE
---------------------------------->
server closes socket
Вот мой код клиента:
#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
from random import randint
image = "tux.png"
HOST = '127.0.0.1'
PORT = 6666
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (HOST, PORT)
sock.connect(server_address)
try:
# open image
myfile = open(image, 'rb')
bytes = myfile.read()
size = len(bytes)
# send image size to server
sock.sendall("SIZE %s" % size)
answer = sock.recv(4096)
print 'answer = %s' % answer
# send image to server
if answer == 'GOT SIZE':
sock.sendall(bytes)
# check what server send
answer = sock.recv(4096)
print 'answer = %s' % answer
if answer == 'GOT IMAGE' :
sock.sendall("BYE BYE ")
print 'Image successfully send to server'
myfile.close()
finally:
sock.close()
И мой сервер, который получает изображения от клиентов:
#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
from random import randint
imgcounter = 1
basename = "image%s.png"
HOST = '127.0.0.1'
PORT = 6666
connected_clients_sockets = []
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
connected_clients_sockets.append(server_socket)
while True:
read_sockets, write_sockets, error_sockets = select.select(connected_clients_sockets, [], [])
for sock in read_sockets:
if sock == server_socket:
sockfd, client_address = server_socket.accept()
connected_clients_sockets.append(sockfd)
else:
try:
data = sock.recv(4096)
txt = str(data)
if txt.startswith('SIZE'):
tmp = txt.split()
size = int(tmp[1])
print 'got size'
sock.send("GOT SIZE")
elif txt.startswith('BYE'):
sock.shutdown()
elif data:
myfile = open(basename % imgcounter, 'wb')
data = sock.recv(40960000)
if not data:
myfile.close()
break
myfile.write(data)
myfile.close()
sock.send("GOT IMAGE")
sock.shutdown()
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
imgcounter += 1
server_socket.close()
Для примера изображения:
Клиент распечатывает сообщения, которые предполагают, что он успешно отправил изображение на сервер:
answer = GOT SIZE
answer = GOT IMAGE
Image successfully send to server
Изображение создается на стороне сервера, но я не могу его открыть. И да, я пробовал разные образы. Без успеха. Я не могу открыть их на стороне сервера, хотя они доступны там.
Благодаря @BorrajaX мне удалось заставить его работать! Спасибо!:)
#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
from random import randint
imgcounter = 1
basename = "image%s.png"
HOST = '127.0.0.1'
PORT = 6666
connected_clients_sockets = []
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
connected_clients_sockets.append(server_socket)
while True:
read_sockets, write_sockets, error_sockets = select.select(connected_clients_sockets, [], [])
for sock in read_sockets:
if sock == server_socket:
sockfd, client_address = server_socket.accept()
connected_clients_sockets.append(sockfd)
else:
try:
data = sock.recv(4096)
txt = str(data)
if data:
if data.startswith('SIZE'):
tmp = txt.split()
size = int(tmp[1])
print 'got size'
sock.sendall("GOT SIZE")
elif data.startswith('BYE'):
sock.shutdown()
else :
myfile = open(basename % imgcounter, 'wb')
myfile.write(data)
data = sock.recv(40960000)
if not data:
myfile.close()
break
myfile.write(data)
myfile.close()
sock.sendall("GOT IMAGE")
sock.shutdown()
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
imgcounter += 1
server_socket.close()
1 ответ
Хорошо, ваша проблема в том, что в случае получения реального изображения вы читаете сокет два раза и игнорируете данные в первом чтении и просто записываете данные, полученные во втором чтении. Таким образом, ваш файл изображения является неполным. Смотрите мое исправление ниже, вы можете оптимизировать его, взяв его за отправную точку. Это работает как таковое.
#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
from random import randint
imgcounter = 1
basename = "image%s.png"
HOST = '127.0.0.1'
PORT = 6666
connected_clients_sockets = []
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
connected_clients_sockets.append(server_socket)
buffer_size = 4096
while True:
read_sockets, write_sockets, error_sockets = select.select(connected_clients_sockets, [], [])
for sock in read_sockets:
if sock == server_socket:
sockfd, client_address = server_socket.accept()
connected_clients_sockets.append(sockfd)
else:
try:
print ' Buffer size is %s' % buffer_size
data = sock.recv(buffer_size)
txt = str(data)
if txt.startswith('SIZE'):
tmp = txt.split()
size = int(tmp[1])
print 'got size'
print 'size is %s' % size
sock.send("GOT SIZE")
# Now set the buffer size for the image
buffer_size = 40960000
elif txt.startswith('BYE'):
sock.shutdown()
elif data:
myfile = open(basename % imgcounter, 'wb')
# data = sock.recv(buffer_size)
if not data:
myfile.close()
break
myfile.write(data)
myfile.close()
sock.send("GOT IMAGE")
buffer_size = 4096
sock.shutdown()
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
imgcounter += 1
server_socket.close()