2016-12-10 173 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