簡體   English   中英

使用套接字 python 發送多個圖像作為一個發送到客戶端

[英]sending multiple images using socket python get sent as one to client

我正在從服務器捕獲屏幕截圖,然后將其發送到客戶端,但是圖像全部作為一個大文件發送到大小不斷擴大的客戶端。 這只發生在我從一台機器發送到另一台機器時(我在本地網絡上工作)但是當從我的機器上運行客戶端和服務器時它們工作正常。 注意:對於其他機器上的客戶端,我使用pyinstaller將其打包成exe,因為這台機器沒有python。

服務器代碼:

host="192.168.43.79"                # Set the server address to variable host
port=4446                   # Sets the variable port to 4446
import time
import pyautogui
from socket import *
import os
s=socket(AF_INET, SOCK_STREAM)

s.bind((host,port))                 

print("Listening for connections.. ")

q,addr=s.accept()
            
i = 0                      
while True:

    screenshot = pyautogui.screenshot()
    screenshot.save(str(i) + ".jpg")
    with open(str(i) + ".jpg", "rb") as f:
        data = f.read(4096)
        while data:
            q.send(data)
            data = f.read(4096)
    q.send(b"full")
    i += 1
    time.sleep(0.3)           


客戶端代碼:


host="192.168.43.79"            # Set the server address to variable host
 
port=4446               # Sets the variable port to 4446
 
from multiprocessing.reduction import recv_handle
from socket import *             # Imports socket module
 
s=socket(AF_INET, SOCK_STREAM)      # Creates a socket
s.connect((host,port)) 

i = 0
while True:
    with open(str(i) + "s.jpg", "wb") as f:
        recv_data = s.recv(4096)            
        while recv_data:
            f.write(recv_data)
            recv_data = s.recv(4096)
            if(recv_data == b"full"):
                break
    i += 1

這里有各種錯誤的假設會導致您看到的問題。 錯誤的假設是:

  • send(data)將寫入所有數據
    它可能會發送更少。 您需要檢查返回值或使用sendall來確定。
  • 發件人中的單個send與收件人中的單個recv完全匹配
    TCP 只是一個非結構化字節 stream。 send不添加消息語義,因此單個send可能會導致多個recv ,多個send可能會導致單個recv等。特別是send("data")后跟send("full")可能是recv(4096)"datafull" ,因此缺少檢測圖像結尾的代碼。

至於為什么它在本地機器上工作而不是在遠程機器上工作 - 在后一種情況下, send合並在一起並將recv合並為一個的機會更高。

正如 Steffen Ulrich 所說,您應該使用sendall進行發送和接收,我們創建了一個專門的 function my_recv ,它將重復調用socket.recv直到收到預期的字節數。 此外,在發送實際文件數據之前,包含文件長度的二進制表示的 4 字節 header(如果您的文件大小允許,您可以使長度更大)。 通過這種方式,客戶端確切地知道它應該為每個文件接收多少數據。

服務器代碼

host="192.168.43.79"                # Set the server address to variable host
port=4446                   # Sets the variable port to 4446
import time
import pyautogui
from socket import *
import os
s=socket(AF_INET, SOCK_STREAM)

s.bind((host,port))
s.listen(1) # This should be called

print("Listening for connections.. ")

q,addr=s.accept()

i = 0
while True:

    screenshot = pyautogui.screenshot()
    screenshot.save(str(i) + ".jpg")
    with open(str(i) + ".jpg", "rb") as f:
        # Get length by positioning to end of file
        image_length = f.seek(0, 2)
        f.seek(0, 0) # Seek back to beginning of file
        # Convert image length to a 4-byte array:
        image_length_bytes = image_length.to_bytes(4, 'big')
        q.sendall(image_length_bytes)
        data = f.read(4096)
        while len(data):
            q.sendall(data)
            data = f.read(4096)
    i += 1

客戶代碼

host="192.168.43.79"            # Set the server address to variable host

port=4446               # Sets the variable port to 4446

from multiprocessing.reduction import recv_handle
from socket import *             # Imports socket module

s=socket(AF_INET, SOCK_STREAM)      # Creates a socket
s.connect((host,port))

def my_recv(msg_length):
    chunks = []
    bytes_to_recv = msg_length
    while bytes_to_recv:
        chunk = s.recv(bytes_to_recv)
        if chunk == b'':
            raise RuntimeError("socket connection broken")
        chunks.append(chunk)
        bytes_to_recv -= len(chunk)
    return b''.join(chunks)

i = 0
while True:
    image_length_bytes = my_recv(4)
    image_length = int.from_bytes(image_length_bytes, 'big')
    with open(str(i) + "s.jpg", "wb") as f:
        bytes_to_recv = image_length
        while bytes_to_recv:
            recv_data = my_recv(min(4096, bytes_to_recv))
            f.write(recv_data)
            bytes_to_recv -= len(recv_data)

    i += 1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM