如何使用 Socket python 在客户端/服务器架构中发送图像

问题描述 投票:0回答:1

我正在尝试使用 python 中的套接字将图像从服务器发送到客户端。但是当客户端收到图像时,我尝试使用 Image() 和 Byteio() 显示它,但显示错误:

我试图找出这个错误是从哪里来的,所以我尝试显示客户端接收到的图像的位大小,并将其与服务器端的图像的位大小进行比较,然后我意识到有一个不同之处。服务器端的位大小大于客户端的位大小。也许这就是问题所在。如果是这样,你如何处理这个问题?或者如何使用 Python 中的套接字通过客户端/服务器架构传输图像?

我的服务器代码:

import socket
import mysql.connector
from mysql.connector import errorcode
import json
from datetime import datetime
from io import BytesIO
from PIL import Image

host = 'localhost'
port = 50000

mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mySocket.bind((host, port))
mySocket.listen()

while 1:
    connexion, adresse = mySocket.accept()
    with open('WhatsApp Image 2023-10-16 at 17.49.56.jpeg', 'rb') as fichier_image:
        image = fichier_image.read()
    if type(image)==bytes:
        try:
            taile_image = len(image)
            print(taile_image)
            print(taile_image.to_bytes(4, byteorder='big'))
            connexion.sendall(taile_image.to_bytes(4, byteorder='big'))
            connexion.sendall(image)
        except:
            pass
    else:
        try:
            resultat_str = json.dumps(resultat, default=str)
            connexion.send(resultat_str.encode('utf8'))
        except:
            pass
    connexion.close()
    ch = input("<R>ecommencer <T>erminer ? ")
    if ch.upper() == "T":
        break
mySocket.close()

这是我的客户端代码:

import socket, threading
import json
from io import BytesIO
from PIL import Image

host = 'localhost'
port = 50000

class ThreadEmission(threading.Thread):
    def __init__(self, conn):
        threading.Thread.__init__(self)
        self.connexion = conn 

    def run(self):
        ident = 2
        pays='Guinée'
        msgClient = "SELECT logo FROM entreprise WHERE identreprise=%s"%ident
        self.connexion.send(msgClient.encode('utf8'))
        

class ThreadReception(threading.Thread):
    def __init__(self, conn):
        threading.Thread.__init__(self)
        self.connexion = conn 
        self.resultat = None

    def run(self):
        
        #print(msgServeur)
        try:
            msgServeur = self.connexion.recv(1024).decode('utf8')
            self.resultat = json.loads(msgServeur)
        except :
            taille_image_bytes = self.connexion.recv(4)
            print('taille_image_bytes ',taille_image_bytes)
            taille_image = int.from_bytes(taille_image_bytes, byteorder='big')
            print('taille_image', taille_image)
            self.resultat= self.connexion.recv(taille_image)
            print(len(self.resultat))       
            #print (type(msgServeur))

        self.connexion.close()
        
    def get_resultat(self):
        return self.resultat
            

myClient = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
myClient.connect((host, port))

th_E = ThreadEmission(myClient)
th_R = ThreadReception(myClient)    
#th_E.start()
th_R.start()
#th_E.join()
th_R.join()
resultat = th_R.get_resultat()
print(resultat)

print(type(resultat))
image = Image.open(BytesIO(resultat))
image.show()
python sockets client-server
1个回答
0
投票

这是一个最小的示例,服务器在客户端连接上发送一张图像,客户端接收该图像。正如评论中提到的,OP 代码具有不相关的代码来处理可能的 JSON 响应,该响应超出了问题的范围,并且干扰了图像的接收。

请注意,

recv(n)
在断开连接时接收 1-n 个字节或 0。您负责缓冲数据,直到收到完整的消息。在这种情况下,请确保您准确读取了四个字节的长度,然后准确读取了数据的“length”字节。使用
socket.makefile
可以通过将套接字包装在类似文件的对象中来帮助缓冲,其中
.read(n)
可精确读取 n 个字节,除非遇到错误或 EOF(套接字关闭)。

服务器:

import socket

with socket.socket() as sock:
    sock.bind(('', 50000))
    sock.listen()

    while True:
        client, addr = sock.accept()
        print(f'{addr}: connected')
        with open('downloads/crawdad.jpg', 'rb') as file:
            image = file.read()
        with client:
            length = len(image)
            client.sendall(length.to_bytes(4, byteorder='big'))
            client.sendall(image)
        print(f'{addr}: disconnected')

客户:

import socket
import threading
import io
from PIL import Image

with socket.socket() as sock:
    sock.connect(('localhost', 50000))
    with sock.makefile('rb') as infile:
        header = infile.read(4)
        if header:
            length = int.from_bytes(header, byteorder='big')
            image = infile.read(length)
            image = Image.open(io.BytesIO(image))
            image.show()
© www.soinside.com 2019 - 2024. All rights reserved.