在Python中使用套接字(ONLY)发送图像,图像无法打开
问题描述:
我想使用Python中的只有套接字将图像从客户端上传到服务器。我设计的我怎么也想做到这一点很简单的协议流程:在Python中使用套接字(ONLY)发送图像,图像无法打开
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()
答
好你的问题是,在实际图像的情况下收到的,你正在阅读的插座两次,第一读忽略的数据,并只是写在第二读取接收到的数据。所以你的图像文件不完整。看到我下面的修复,你可以从这个优化作为出发点。它的工作原理如此。
#!/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()
未经测试(这就是为什么我没有做这个答案),它看起来像你的服务器获取第一'4096'字节到你的'data'变量,但那些永远不会写进文件。在'elif data:'你用'data = sock.recv(40960000)'覆盖'data',所以第一个'4096'永远不会写入'myfile'文件。也许是吗? – BorrajaX
@BorrajaX:是的,就是这样!我在'myfile = open(basename%imgcounter,'wb')'行后面添加了'myfile.write(data)',现在我可以打开图像! :)但是,它现在看起来很丑(代码)。你有什么想法如何改进它?为了不要有两个'myfile.write(data)'? – yak
@BorrajaX:当客户端发送与'协议'和图像中定义的消息不同的东西时,我该如何避免错误?在这种情况下,我想断开它。 – yak