Python socket Select 模块显示它收到了读取请求,而它只收到了一个。为什么?

Python socket Select module showing it received to read requests, when it only received one. Why?

我正在创建一个程序,客户端在其中输入包含图像的文件的名称。然后它被转换成一个 numpy 数组,pickle 并发送到服务器。服务器使用 PIL ImageDraw 在所述图像的顶部绘制一个红色 X,然后将其发送回客户端。我注意到 select 函数出于某种原因将套接字两次添加到读取列表中。我知道这一点,因为客户端取回了图像,并且我在发送过程结束时添加了一个打印功能,它触发了一次,但是之前的打印语句再次消失,并返回了一个错误。这是服务器输出:

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()

谢谢!

I have noticed that the select function adds the socket twice to the read list for some reason.

没有。 select returns 只要套接字上有可以使用 recv 检索的信息,套接字就是可读的。当您处理 recv returns 实际数据的情况时,您不会处理 recv returns 空缓冲区(即 '')的情况如果对等方关闭连接。换句话说:问题不在于 select,而是您对 selectrecv 工作方式的假设。