Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python套接字选择模块显示它接收到的读取请求,而它只接收到一个请求。为什么?_Python_Sockets_Select_Python Sockets - Fatal编程技术网

Python套接字选择模块显示它接收到的读取请求,而它只接收到一个请求。为什么?

Python套接字选择模块显示它接收到的读取请求,而它只接收到一个请求。为什么?,python,sockets,select,python-sockets,Python,Sockets,Select,Python Sockets,我正在创建一个程序,其中客户端以包含图像的文件名输入。然后将其转换为numpy数组,进行pickle处理并发送到服务器。服务器使用PIL ImageDraw在所述图像的顶部绘制一个红色X,然后将其发送回客户端。我注意到,由于某种原因,select函数将套接字两次添加到读取列表中。我知道这一点,因为客户端获取了图像,我在发送过程结束时添加了一个print函数,它触发了一次,但是之前的print语句再次出现,并返回了一个错误。以下是服务器输出: b'56925 ' sent b''

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

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

我注意到,由于某种原因,select函数将套接字两次添加到读取列表中


没有。select返回只要套接字上有可以使用recv检索的信息,该套接字就可读。当您处理recv返回实际数据的情况时,您不会处理recv返回空缓冲区的情况,即当对等方关闭连接时它会这样做。换句话说:问题不在于选择,而在于您对选择和录制工作方式的假设。

非常感谢!我现在明白了。每次客户端试图接收某个信息时,函数的写入部分是否也会这样做?@ReiMeytal:函数的写入部分是否也会这样做?我真的不明白你的意思。我的意思是:select的写入部分是否会在客户端每次侦听消息时触发?@ReiMeytal:只要本地套接字缓冲区中有空间,select的写入部分就会触发,这样写入就不会阻塞。它没有对等方当前正在做什么的信息。请检查您的返回值!recv3000不保证返回3000字节。有关示例和修复,请参见。