Pygame не работает с сокетами - PullRequest
2 голосов
/ 01 октября 2011

Я создал одну программу с pygame, imageGrab и сокетами, но она не работает. Он должен сделать снимок экрана сервера с ImageGrab, преобразовать его в строку и отправить клиенту. Однако клиент, получив информацию и преобразовав ее в изображение, выдает ошибку:

image = pygame.image.frombuffer(img, (800,600), "RGB")
ValueError: Buffer length does not equal format and resolution size 

код сервера

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()

код клиента

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 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()

1 Ответ

2 голосов
/ 02 октября 2011

Работа с сокетами заключается в том, что вы должны точно знать, как долго будет получено сообщение, если вы планируете продолжать использовать то же соединение с сокетом.Кажется, у вас есть представление об этом с вашим q_bytes = raw_input("Enter the number of MBs to transfer: "), но нам нужно знать точно , а не с точностью до ближайшего МБ.Иногда эта информация отправляется в передней части данных, поэтому мы можем сначала прочитать ее, а затем узнать, когда прекратить чтение.

Исключением является то, что нам больше не нужно соединение;мы просто хотим эту картинку.В этом случае нормально запросить столько данных, сколько мы хотим, в конце мы получим пустую строку.

Что касается аргумента max_bytes для recv, то это всего лишь один максимум - есть еще один аппаратно-зависимый максимум, на который мы наложили тесты: 1 МБ.

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

Существует много уровней абстракции, которые могут (и должны) быть построены, чтобы дистанцировать нас от этих сложностей, но приведенный ниже код только ваш, работает, с некоторыми несущественными битами.

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: Согласно исправлению Марка, вызовы len () ранее были __sizeof__() вызовами метода.__sizeof__ возвращает размер объекта python в байтах, а не количество байтов / символов в строке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...