python - Python socket Select 模块显示它已收到读取请求,但它只收到一个。为什么?
问题描述
我正在创建一个程序,客户端在其中输入包含图像的文件的名称。然后将其转换为 numpy 数组,腌制并发送到服务器。服务器使用 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()
谢谢!
解决方案
我注意到 select 函数出于某种原因将套接字两次添加到读取列表中。
它没有。select
只要有关于可以使用 检索的套接字的信息,就会返回该套接字是可读的recv
。当您处理recv
返回实际数据的情况时,您不会处理当对等方关闭连接时recv
返回空缓冲区(即)的情况。''
换句话说:问题不在于select
您对如何select
和recv
工作的假设。
推荐阅读
- java - 是什么导致 Hibernate 中的已提交更新对其他线程不可见?
- python - MP3 标签不保存在 Python 中
- django - 具有自定义属性的 Django 查询集
- php - Zxing Barcode Scanner Php 在手机上选择后置摄像头
- react-native - undefined 不是反应原生的对象(评估'this.props.route.params.lead_tag_number.data')
- mapbox - 添加图标光环作为上传为 Mapbox 图标的图像的边框
- javascript - 如何在 JavaScript Canvas 中绘制垂直于直线或曲线切线的矩形
- node.js - 静态文件不在 Node.js 中提供
- javascript - 如何从对象内部的字符串中删除一些文本并且对象在数组中?
- javascript - 使用 cmd 的 JavaScript I/O