在 Python 中通过套接字发送图像(仅),图像无法打开
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42458475/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sending image over sockets (ONLY) in Python, image can not be open
提问by yak
I want to upload the image from client to server using ONLY sockets in Python. I designed a very simple protocol flow of how I would like to do this:
我想仅使用 Python 中的套接字将图像从客户端上传到服务器。我设计了一个非常简单的协议流程,说明我想如何做到这一点:
CLIENT SERVER
SIZE 512 (send image size)
---------------------------------->
GOT SIZE
<----------------------------------
send image itself
---------------------------------->
GOT IMAGE
<----------------------------------
BYE BYE
---------------------------------->
server closes socket
Here's my client code:
这是我的客户端代码:
#!/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()
And my server, which receives images from clients:
还有我的服务器,它从客户端接收图像:
#!/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()
For the example image:
对于示例图像:
The client prints out messages, that suggest, that it send the image to server successfully:
客户端打印出消息,表明它已成功将图像发送到服务器:
answer = GOT SIZE
answer = GOT IMAGE
Image successfully send to server
The image is created at server's side, but I can not open it. And yes, I tried different images. With no success. I can't open them at server's side, even though they are available there.
图像是在服务器端创建的,但我无法打开它。是的,我尝试了不同的图像。没有成功。我无法在服务器端打开它们,即使它们在那里可用。
Thanks to @BorrajaX, I managed to make it work! Thanks! :)
感谢@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()
采纳答案by gipsy
Okay your problem is, in the case of actual image received, you are reading the socket two times and ignoring the data in the first read and just writing the data received in the second read. So your image file is incomplete. See my fix below , you can optimize from this taking it as starting point. It works as such.
好的,您的问题是,在接收到实际图像的情况下,您正在读取套接字两次并忽略第一次读取中的数据,而只写入在第二次读取中接收到的数据。所以你的图像文件不完整。请参阅下面的我的修复,您可以以此为起点进行优化。它是这样工作的。
#!/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()