【发布时间】:2017-01-02 14:11:16
【问题描述】:
我在这里相当菜鸟,但尝试设置一个脚本,我可以在其中轮询套接字,当没有发送套接字数据时,循环继续运行并执行其他操作。我一直在玩我使用 select() 找到的几个示例,但无论我如何组织代码,它似乎都停在 server.recv() 行上或附近并等待响应。如果客户端没有发送数据,或者不存在客户端连接,我想跳过这个。
请注意,此应用程序不需要服务器脚本发送任何回复数据,如果它有什么不同的话。
实际应用程序是运行一个循环并为一些 LED 设置动画(这需要对 Raspberry Pi 上的 I/O 进行 root 访问)。我将通过将传递动画控制参数的套接字从另一个单独的脚本发送此脚本数据。这样外部脚本就不需要root权限了。
到目前为止,数据的发送和接收效果很好,在没有传入数据的情况下,我无法让循环继续旋转。据我了解,这是 select() 旨在允许的,但我发现的示例似乎并非如此。
我尝试在几个不同的地方添加 server.setblocking(0) 无济于事。 (如果我理解正确,如果没有发送数据,非阻塞实例应该允许代码跳过 recv() ,但我可能会关闭这个)。
我的代码基于此处的示例: http://ilab.cs.byu.edu/python/select/echoserver.html
这是服务器端脚本,后面是客户端脚本。
服务器代码:sockselectserver.py
#!/usr/bin/env python
import select
import socket
import sys
server = socket.socket()
host = socket.gethostname()
port = 20568
size = 1024
server.bind((host,port))
server.listen(5)
input = [server,sys.stdin]
running = 1
while running:
inputready,outputready,exceptready = select.select(input,[],[])
for s in inputready:
if s == server:
# handle the server socket
client, address = server.accept()
input.append(client)
elif s == sys.stdin:
# handle standard input
junk = sys.stdin.readline()
running = 0
else:
# handle all other sockets
data = s.recv(size)
if data:
s.send(data)
else:
s.close()
input.remove(s)
print "looping"
server.close()
客户端代码:skclient.py
#!/usr/bin/python # This is client.py file
import socket # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 20568 # Reserve a port for your service.
s.connect((host, port))
data = "123:120:230:51:210:120:55:12:35:24"
s.send(data)
print s.recv(1024)
s.close # Close the socket when done
我想通过这个例子实现的是看到“循环”永远重复,然后当客户端脚本发送数据时,看到数据打印,然后看到“循环”一遍又一遍地恢复打印。这会告诉我它正在做我可以从那里得到它的意图。
有趣的是,当我按原样进行测试时,每当我运行客户端时,我都会在屏幕上看到“循环”打印 3 次,然后就没有了。我不完全理解 select 内部发生了什么,但我认为它只会打印 1 次。
我尝试将 inputready.. select.select() 移动到不同的地方,但发现它似乎每次都需要调用,否则服务器会停止响应(例如,如果它在无休止的 while 之前调用一次:循环)。
我希望这可以简单到可以在创客课程中教授给其他黑客类型,所以我希望我不需要对多线程和更复杂的解决方案过于疯狂。作为最后的手段,我正在考虑将所有参数从外部脚本记录到 mySQL,然后使用此脚本从表中查询它们。我在那里有经验,可能会工作,但似乎这个插座角度会是一个更直接的解决方案。
非常感谢任何帮助。
【问题讨论】:
-
服务器必须是自己的循环 imo
-
感谢您的快速回复。我不确定我将如何实现这一点。你能分享一个示例代码片段吗?我是否会将所有内容都包装在一个循环中,如果是这样,我将在哪里调用我的其他函数(那些将被一遍又一遍地调用,仅在客户端发送传入数据时中断的函数)?
-
尝试使用超时(以秒为单位)选项调用
select.select():select.select(input,[],[],1)。 -
这可能会奏效 - 将在早上尝试。你能澄清一下这是如何工作的吗?我可能会将超时设置得很短——可能是 0.05 秒(这是否太短而无法工作?)——所以我可以很快回到动画灯光。例如,如果我的动画循环需要 1 秒(只是指出动画部分相当长,而 select.select() 相当短) - 如果客户端在此动画部分期间发送数据,当 select.select()没有运行,数据是否会被缓冲,然后在下次 select.select() 运行时可用并找到?
标签: python multithreading sockets select