[英]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
完全匹配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.