Python socket Выберите модуль, показывающий, что он получил запросы на чтение, когда он получил только один. Почему? - PullRequest
0 голосов
/ 04 апреля 2020

Я создаю программу, в которую клиент вводит имя файла, содержащего изображение. Затем он преобразуется в массив numpy, обрабатывается и отправляется на сервер. Сервер использует PIL ImageDraw, чтобы нарисовать красный крестик на вершине указанного изображения, а затем отправляет его обратно клиенту. Я заметил, что функция выбора по какой-то причине дважды добавляет сокет в список чтения. Я знаю это, так как клиент возвращает изображение, и я добавил функцию печати в конце процесса отправки, и он сработал один раз, но затем более ранний оператор печати снова отключился и возвратил ошибку. Вот вывод сервера:

b'56925          '
sent
b''
Traceback (most recent call last):
  File "server.py", line 31, in <module>
    msglengthi = int(msglength)
ValueError: invalid literal for int() with base 10: ''

Вот код сервера:

import socket
import pickle
from PIL import ImageDraw
from PIL import Image
import select
import numpy

IP = socket.gethostbyname(socket.gethostname())
PORT = 4321
HEADERSIZE = 15

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((IP, PORT))
s.listen(5)
socketlist = [s]
readqueue = []


while True:
    readqueue, write, exception  = select.select(socketlist, [], [])
    for socket in readqueue:
        if socket == s:
            clientsocket, clientaddress = s.accept()
            socketlist.append(clientsocket)
            print(f"Connection received from {clientaddress}")
            clientsocket.send(bytes("Welcome to the server", "utf-8"))
        else:
            msglen = socket.recv(HEADERSIZE)
            msglength = msglen.decode("utf-8")
            print(msglen)
            msglengthi = int(msglength)
            fullmsg = []
            x=0
            while x<=msglengthi:
                msgu = socket.recv(3000)
                fullmsg.append(msgu)
                x+=3000
            fullmsg = b"".join(fullmsg)
            msg = pickle.loads(fullmsg)
            img = Image.fromarray(msg)
            draw = ImageDraw.Draw(img)
            width, height = img.size
            draw.line((0, 0, width, height), fill="red", width=20)
            draw.line((width, 0, 0, height), fill="red", width=20)
            payload = pickle.dumps(numpy.array(img))
            paylen = len(payload)
            socket.send(bytes(f"{paylen:<{HEADERSIZE}}", "utf-8")+payload)
            print("sent")

и, наконец, код клиента:

import socket
import pickle
from PIL import Image
import numpy


PORT = 4321
IP = socket.gethostbyname(socket.gethostname())
HEADERSIZE = 15

cs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cs.connect((IP, PORT))
welcomemsg = cs.recv(21)
welcomemsg = welcomemsg.decode("utf-8")
print(welcomemsg)

img = input("Enter image file: ")
imgo = Image.open(img)
imga = numpy.array(imgo)
imgdump = pickle.dumps(imga)
msglen = len(imgdump)
print(msglen)
cs.send(bytes(f"{msglen:<{HEADERSIZE}}", "utf-8")+imgdump)
msglen = cs.recv(HEADERSIZE)
msglen = msglen.decode("utf-8").strip()
msglen = int(msglen)
x=0
fullmsg=[]
while x<=msglen:
    msg = cs.recv(3000)
    fullmsg.append(msg)
    x+=3000
fullmsg = b"".join(fullmsg)
img = pickle.loads(fullmsg)
img = Image.fromarray(img)
img.show()

Спасибо!

1 Ответ

1 голос
/ 04 апреля 2020

Я заметил, что функция выбора почему-то дважды добавляет сокет в список чтения.

Это не так. select возвращает, что сокет доступен для чтения при наличии информации о сокете, которую можно получить с помощью recv. Хотя вы обрабатываете случай, когда recv возвращает фактические данные, вы не обрабатываете случай, когда recv возвращает пустой буфер (т. Е. ''), что происходит, если узел закрывает соединение. Другими словами: проблема не в select, а в вашем предположении о том, как select и recv работают.

...