2016-12-10 174 views
2

我想发送服务器的屏幕截图到客户端,为了做到这一点,我想发送图像作为字节,并将其分割成部分,每部分的长度为1024.通过套接字发送图像作为字节

首先,程序做了多件事情,它也发送文件,时间等等。所以客户端需要告诉服务器他/(它)?想要一张图片,所以他首先发送'Img',然后服务器返回'Img',当客户端收到'Img'后,他开始收听所有部分,服务器开始发送所有部分,当最后一部分发送,服务器发送'发送'。

到目前为止我的代码:Client.py:

def listen_for_image(): 
    bytes_data = socket_con.recv(1024) 
    part = bytes_data 
    i = 1 
    print("Part #", str(i)) 
    while part.decode() != 'Sent': 
     part = socket_con.recv(1024) 
     bytes_data += part 
     i += 1 
     print("Part #", str(i)) 
    return bytes_data 


    socket_con.send('Img') 
    data_back = socket_con.recv(1024) 
    if data_back.decode() == 'Img': 
     bytes_full_data = listen_for_image() 
     img = Image.frombytes('RGB', (1366, 768), bytes_full_data) 
     img.save('newimg.jpg') 

Server.py:

def send_screen_shot(): 
    con.send('Img'.encode()) 
    image = ImageGrab.grab() 
    start = 0 
    end = 1024 
    while end < len(image.tobytes()): 
     con.send(image.tobytes()[start:end]) 
     start = end + 1 
     end += 1024 
    con.send("Sent".encode()) 


if con.recv(1024).decode() == 'Img': 
     send_screen_shot() 

请注意,我的计划做更多,所以这是不完整的代码,但只需要的部分,如果你需要别的东西,只要问:)

我的代码的问题是,在客户端我得到一个错误:

Traceback (most recent call last): 
    File "C:/Users/dodob/PycharmProjects/untitled/client.py", line 33, in <module> 
    bytes_full_data = listen_for_image() 
    File "C:/Users/dodob/PycharmProjects/untitled/client.py", line 14, in listen_for_image 
    while part.decode() != 'Sent': 
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte 

编辑: 我试着开关,编码器,以解决这一问题,例如:

Client.py:

def listen_for_image(): 
    bytes_data = socket_con.recv(1024) 
    part = bytes_data 
    i = 1 
    print("Part #", str(i)) 
    while part.decode('ISO-8859-1') != 'Sent': 
     part = socket_con.recv(1024) 
     bytes_data += part 
     i += 1 
     print("Part #", str(i)) 
    return bytes_data 

Server.py:

def send_screen_shot(): 
    con.send('Img'.encode()) 
    image = ImageGrab.grab() 
    start = 0 
    end = 1024 
    while end < len(image.tobytes()): 
     con.send(image.tobytes(encoder_name='ISO-8859-1')[start:end]) 
     start = end + 1 
     end += 1024 
    con.send("Sent".encode('ISO-8859-1')) 

但后来我得到一个错误在服务器端:

Traceback (most recent call last): 
    File "C:\Python\Python35\lib\site-packages\PIL\Image.py", line 437, in _getencoder 
    encoder = getattr(core, encoder_name + "_encoder") 
AttributeError: module 'PIL._imaging' has no attribute 'ISO-8859-2_encoder' 

During handling of the above exception, another exception occurred: 

Traceback (most recent call last): 
    File "C:/Users/dodob/PycharmProjects/untitled/server.py", line 42, in <module> 
    send_screen_shot() 
    File "C:/Users/dodob/PycharmProjects/untitled/server.py", line 19, in send_screen_shot 
    con.send(image.tobytes(encoder_name='ISO-8859-2')[start:end]) 
    File "C:\Python\Python35\lib\site-packages\PIL\Image.py", line 681, in tobytes 
    e = _getencoder(self.mode, encoder_name, args) 
    File "C:\Python\Python35\lib\site-packages\PIL\Image.py", line 441, in _getencoder 
    raise IOError("encoder %s not available" % encoder_name) 
OSError: encoder ISO-8859-2 not available 

而且客户端保持运行是这样的:

... 
Part # 2376824 
Part # 2376825 
Part # 2376826 
Part # 2376827 
Part # 2376828 
Part # 2376829 
Part # 2376830 
Part # 2376831 
Part # 2376832 
Part # 2376833 
Part # 2376834 
... 

我觉得这个错误造成的,因为没有这样的编码器,但我尝试了多个,每次都会发生......但无论如何,我不知道客户端为什么会继续运行,因此recv函数应该停止运行,直到它收到一些东西,并且它在这里永远运行。

感谢您的帮助。

回答

3

只需使用

while part != b'Sent': 

和整个风格相同。你的问题是你正在尝试解码图像中的二进制数据以及文本。不是。而且您不需要将其转换为文本以便与已知值进行比较 - 您只需使用字节作为已知值。

你也想改变这一点:

while end < len(image.tobytes()): 
    con.send(image.tobytes(encoder_name='ISO-8859-1')[start:end]) 
    start = end + 1 
    end += 1024 
con.send("Sent".encode('ISO-8859-1')) 

要这样:

img_bytes = image.tobytes() 
while end < len(img_bytes): 
    con.send(img_bytes[start:end]) 
    start = end + 1 
    end += 1024 
con.send("Sent".encode()) 

那将节省您的图像每次重新转换为字节。如果您的图像大小为1024000字节,则会调用该函数2,000次。不要这样做。这可能不是一个严重的问题,因为网络传输速度要慢几个数量级,但是根据图像的大小,您仍然可以从十分之一秒到十分钟的时间内完成任何修剪。

哦,还有另一件事:

while part and part != b'Sent': 
    part = socket_con.recv(1024) 
    bytes_data += part 
    i += 1 
    print("Part #", str(i)) 

如果套接字关闭你居然会退出你的循环这种方式。当套接字关闭时,保证.recv将返回一个空字符串(字节)。这评估为False,所以如果你收到没有数据那么它将退出这个循环。

+0

这是伟大的,这部分现在的工作,它提出了另一个错误,但我会为了解决它的工作! – DAVIDBALAS1

+0

Emm,一个简单的问题 - 如果例如字节长度是4608,我需要从0发送到4608,包括两个?意思是0(含) - 1024,1025 - 2048,2049 - 3072,3073 - 4096,4097 - 4608(含) – DAVIDBALAS1

+0

我对你的要求有些困惑。我认为你有足够的代表来[在python房间里聊天](http://chat.stackoverflow.com/rooms/6/python)。 –

0

如果你通过这样的套接字发送图像,你会注意到还有一些字节还没有被发送。
为了避免这种情况,更换

start = end + 1 

start = end