我在这里是一个菜鸟,但是尝试设置一个我可以轮询套接字的脚本,当没有发送套接字数据时,循环继续运行并执行其他操作。我一直在使用select()找到的几个例子,但无论我如何组织代码,它似乎停在server.recv()行上或附近并等待响应。如果客户端没有发送数据,或者没有客户端连接,我想跳过这个。
请注意,如果此应用程序有任何不同,则此应用程序不需要服务器脚本发送任何回复数据。
实际应用程序是运行循环并为某些LED设置动画(需要root访问Raspberry Pi上的I / O)。我将通过套接字从另一个单独的脚本发送此脚本数据,这些套接字将传递动画的控制参数。这样,外部脚本不需要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中发生了什么,但我认为它只会打印一次。
我尝试将inputready .. select.select()移动到不同的地方,但发现每次都需要调用它,否则服务器会停止响应(例如,如果它在无尽的时间之前被调用一次:循环)。
我希望这可以变得简单,以便可以在制造商类中教授其他黑客类型,所以我希望我不需要对多线程和更复杂的解决方案太过疯狂。作为最后的手段,我正在考虑从外部脚本将所有参数记录到mySQL,然后使用此脚本从表中查询它们。我在那里有经验并且可能会工作,但似乎这个插座角度将是一个更直接的解决方案。
非常感谢任何帮助。
答案 0 :(得分:0)
好消息。这是一个简单的修复,想要发布以防其他人需要它。上面的acw1668的建议让我走了。
简单地添加" 0"像这样的select.select():
inputready,outputready,exceptready = select.select(input,[],[],0)
这是在python文档中但不知何故我错过了它。点击此处:https://docs.python.org/2/library/select.html
根据文档: "可选的timeout参数指定超时为浮点数(以秒为单位)。省略timeout参数时,函数将阻塞,直到至少有一个文件描述符准备就绪。超时值为零指定轮询并且永不阻止。"
我测试了与上面相同的代码,在打印后立即使用time.sleep(5)添加了5秒的延迟"循环"线。随着延迟,如果没有数据或客户端,代码只是每5秒循环一次并打印"循环"到屏幕。如果我在5秒延迟期间启动客户端脚本,它会暂停,并在下一次5秒延迟结束时处理该消息。偶尔它不响应下一个循环,而是循环跟随。我假设这是因为第一次通过server.accept正在运行,下一次通过s.recv()正在运行实际交换数据。