Pygame not working with sockets
I created one program with pygame, imageGrab and sockets but it doesn't work. It should take a printscreen of the server with ImageGrab, convert it to a string, and send it to the client. However, the client upon receiving the information and converting it to an image raises an error:
image = pygame.image.frombuffer(img, (800,600), "RGB")
ValueError: Buffer length does not equal format and resolution size
code Server
import sys, os, socket, pygame
from PIL import ImageGrab
from pygame.locals import *
print "streaming sever 0.1"
try:
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print "Error creating socket"
sys.exit(1)
host = "127.0.0.1"
port = raw_input("Port:")
socket.bind((host, int(port)))
socket.listen(2)
socket2,client = socket.accept()
print "Client conectado: " + str(client[0]) + "\nPorta usada: " + str(client[1])
#Capture and send
while True:
img=ImageGrab.grab().resize((800,600))
img.tostring()
socket2.sendall(img)
socket2.close()
code Client
import sys, os, socket, pygame
from PIL import ImageGrab
from pygame.locals import *
print "streaming client 0.1"
pygame.init()
try:
s_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print "streaming protocol started"
except socket.error:
print "Error creating socket"
sys.exit(1)
host = "127.0.0.1"
porta = raw_input("Port:")
q_bytes = raw_input("Enter the number of MBs to 开发者_JAVA百科transfer: ")
t_bytes = 1024*1024*int(q_bytes)
try:
s_client.connect((host,int(porta)))
except socket.error:
print "Error connecting to: " + host
sys.exit(1)
print "Conectado!"
size = width, height = 800, 600
screen = pygame.display.set_mode(size)
num = 0
while True:
img = s_client.recv(t_bytes)
image = pygame.image.frombuffer(img, (800,600), "RGB")
screen.blit(image,(0,0))
pygame.display.flip()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
os._exit(1)
#recebimento
s_client.close()
The deal with sockets is you have to know exactly how long the message you're receiving is if you plan keep using the same socket connection. You seem to have some idea of this with your q_bytes = raw_input("Enter the number of MBs to transfer: ")
, but we need to know exactly, not to the nearest MB. Sometimes this information is sent at the front part of the data, so we can read it first and then know when to stop reading.
The exception to this is if we don't need the connection anymore; we just want this one picture. In that case, it's fine to ask for as much data as we want, we'll get an empty string back at the end.
As for the max_bytes argument to recv, that's just one maximum - there's another hardware-dependent maximum imposed on us, for my tests it was 1MB.
The code below just keeps asking for data, stops when it receives an empty string because there is no more data, then combines all this gathered data into the full string.
There are many levels of abstraction that could (and should) be built up to distance us from these complications, but the code below is just yours, working, with some irrelevant bits taken out.
Client.py
import sys, os, socket, pygame
from pygame.locals import *
pygame.init()
s_client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host = "127.0.0.1"
porta = 12350
t_bytes = 1024*1024*1
s_client.connect((host,int(porta)))
print "Conectado!"
size = width, height = 300, 500
screen = pygame.display.set_mode(size)
message = []
while True:
s = s_client.recv(t_bytes)
if not s:
break
else:
message.append(s)
full_s = "".join(message)
print 'string received size', len(full_s)
image = pygame.image.frombuffer(full_s, size, "RGB")
#image = pygame.image.fromstring(s, size, "RGB")
screen.blit(image,(0,0))
pygame.display.flip()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
os._exit(1)
raw_input()
s_client.close()
Server.py
import sys, os, socket, pygame
from pygame.locals import *
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "127.0.0.1"
port = 12350
socket.bind((host, int(port)))
socket.listen(2)
socket2,client = socket.accept()
print "Client conectado: " + str(client[0]) + "\nPorta usada: " + str(client
img = Image.open('tiny.jpg').resize((300, 500))
s = img.tostring()
print 'size of string', len(s)
socket2.sendall(s)
socket2.close()
edit: As per Mark's correction, len() calls were previously __sizeof__()
method calls. __sizeof__
returns the size of the python object in bytes, not the number of bytes/characters in the string.
精彩评论