python - 选择 call only 在 tcp 输入上工作两次。如何正确使用 select 与 tcp 和 udp 服务器?
问题描述
我正在创建一个服务器,它使用 select() 在 Python 中进行非阻塞 i/o。
我有一个选择输入为 TCP 连接和 UDP 连接的服务器。在 TCP 连接中,可能会调用其他 UDP 服务器。问题是我的服务器在运行服务器时只检查 TCP 输入两次,并且与其他 UDP 服务器(不是服务器自己的 UDP 服务器)进行了一些数据传输。如果不需要 UDP 传输,那么它的工作次数与 Web 浏览器调用的次数一样多。
除了我只能发送 TCP 请求两次的奇怪情况之外,我的服务器似乎工作正常。
我还怀疑我能够发送两次,因为浏览器的一些 favicon 请求和实际请求将 's' 两次作为输入并且在它之后不起作用。我还认为我如何将 select 用于服务器自己的 UDP 连接可能存在问题。
这是我第一次编写服务器程序,所以一般来说我如何处理选择函数和套接字可能存在一些直截了当的问题。
inputs = [ server, udp ]
# Sockets to which we expect to write
outputs = [ ]
# Outgoing message queues (socket:Queue)
message_queues = {}
while inputs:
# Wait for at least one of the sockets to be ready for processing
print('\nwaiting for the next event')
readable, writable, exceptional = select.select(inputs, outputs, inputs)
这有点像我的可读输入循环的样子:
if s is server:
connection, client_address = s.accept()
connection.setblocking(0)
inputs.append(connection)
message_queues[connection] = queue.Queue()
elif s != udp:
print(readable)
try:
data = s.recv(4096)
if data:
# do something
message_queues[s].put(data)
if s not in outputs:
outputs.append(s)
else:
# Interpret empty result as closed connection
print('closing', client_address, 'after reading no data')
if s in outputs:
outputs.remove(s)
inputs.remove(s)
s.close()
del message_queues[s]
except Exception:
if s in outputs:
outputs.remove(s)
inputs.remove(s)
s.close()
if s is udp:
print(s)
udpdata,addr = s.recvfrom(UDP_PORT_NO)
这有点像我的可写循环的样子:
for s in writable:
try:
next_msg = message_queues[s].get_nowait()
if (something):
udp_others = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# Send data
sent = udp_others.sendto(packet.encode(), ('localhost', destination_port))
# Receive response
clientdata, server = udp_test.recvfrom(4096)
# do something with data
finally:
print ('closing socket')
udp_others.close()
next_msg = "Hello"
except queue.Empty:
# No messages waiting so stop checking for writability.
print('output queue for', s.getpeername(), 'is empty')
outputs.remove(s)
else:
print(response)
# Handle "exceptional conditions"
for s in exceptional:
print >>sys.stderr, 'handling exceptional condition for', s.getpeername()
# Stop listening for input on the connection
inputs.remove(s)
if s in outputs:
outputs.remove(s)
s.close()
# Remove message queue
del message_queues[s]
解决方案
推荐阅读
- javascript - 在没有 Ajax 的情况下将数据从 javascript 前端发送到 Flask 后端的方法
- c# - 我怎样才能创建一个距离限制,玩家将缓慢平稳地停止?
- c# - 您可以将对象从 GroupBy 添加到列表吗?
- java - 如何在 Spring Boot Graphql 中过滤子字段
- android - 如何使用 inputType = none 清除 AutoCompleteTextView
- r - 抑制分类变量 SparkR 的回归输出
- haskell - Xmonad,无法将类型“ModifiedLayout(Sublayout(ModifiedLayout SmartBorder Simplest))l0 a0”与“GHC.Word.Word64”匹配
- python - “无法加载插件:%s:%s”%(self.group,名称)sqlalchemy.exc.NoSuchModuleError:无法加载插件:sqlalchemy.dialects:postgres我该怎么做
- elixir - 什么是使用捕获语法传递的内核函数?
- bootstrap-4 - 带有 Bootstrap 的 Angular 编译器警告