让我们在 python 中考虑这段代码:
import socket
import threading
import sys
import select
class UDPServer:
def __init__(self):
self.s=None
self.t=None
def start(self,port=8888):
if not self.s:
self.s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.s.bind(("",port))
self.t=threading.Thread(target=self.run)
self.t.start()
def stop(self):
if self.s:
self.s.close()
self.t.join()
self.t=None
def run(self):
while True:
try:
#receive data
data,addr=self.s.recvfrom(1024)
self.onPacket(addr,data)
except:
break
self.s=None
def onPacket(self,addr,data):
print addr,data
us=UDPServer()
while True:
sys.stdout.write("UDP server> ")
cmd=sys.stdin.readline()
if cmd=="start\n":
print "starting server..."
us.start(8888)
print "done"
elif cmd=="stop\n":
print "stopping server..."
us.stop()
print "done"
elif cmd=="quit\n":
print "Quitting ..."
us.stop()
break;
print "bye bye"
它运行一个交互式 shell,我可以使用它来启动和停止 UDP 服务器。服务器是通过一个类来实现的,该类启动一个线程,其中在try/except 块内有一个recv / onPacket回调的无限循环,该块应该检测错误并退出循环。我期望的是,当我在 shell 上键入“stop”时,套接字会关闭,并且由于文件描述符无效,recvfrom函数会引发异常。相反,即使在关闭调用之后, recvfrom似乎仍然会阻塞等待数据的线程。为什么会出现这种奇怪的行为?我一直使用这种模式在 C++ 和 JAVA 中实现 UDP 服务器,并且它总是有效。
我还尝试使用“ select ”将带有套接字的列表传递给xread参数,以便从select而不是从recvfrom获取文件描述符中断事件,但select似乎对关闭也“不敏感” .
我需要一个唯一的代码,它在 Linux 和 Windows 上使用 python 2.5 - 2.6 保持相同的行为。
谢谢。