Pygame 不适用于套接字 [英] Pygame not working with sockets

查看:50
本文介绍了Pygame 不适用于套接字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用 pygame、imageGrab 和套接字创建了一个程序,但它不起作用.它应该使用 ImageGrab 获取服务器的打印屏幕,将其转换为字符串,然后将其发送到客户端.但是,客户端在收到信息并将其转换为图像时会引发错误:

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 

代码服务器

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

推荐答案

关于套接字的问题是,如果您计划继续使用相同的套接字连接,您必须确切地知道您收到的消息有多长.您的 q_bytes = raw_input("Enter the number of MBs to transfer:") 似乎对此有所了解,但我们需要确切地知道,而不是最近的 MB.有时这个信息是在数据的前面部分发送的,所以我们可以先读取它,然后知道什么时候停止读取.

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.

至于 recv 的 max_bytes 参数,这只是一个最大值 - 还有另一个硬件相关的最大值强加给我们,对于我的测试,它是 1MB.

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.

客户端.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()

服务器.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()

根据 Mark 的更正,len() 调用以前是 __sizeof__() 方法调用.__sizeof__ 以字节为单位返回 python 对象的大小,而不是字符串中的字节数/字符数.

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.

这篇关于Pygame 不适用于套接字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆