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"
UDP サーバーを起動および停止できる対話型シェルを実行します。サーバーは、エラーを検出してループを終了する必要がある try/except ブロック内にrecv / onPacketコールバックの無限ループがあるスレッドを起動するクラスを通じて実装されます。私が期待しているのは、シェルで「stop」と入力すると、ソケットが閉じられ、ファイル記述子の無効化のためにrecvfrom関数によって例外が発生することです。代わりに、recvfromは、 close呼び出しの後でも、データを待機しているスレッドをブロックしているようです。なぜこの奇妙な動作ですか?私は常にこのパターンを使用して、C++ と Java で UDP サーバーを実装してきましたが、常に機能していました。
recvfromからの代わりにselectからファイル記述子の中断のイベントを取得するために、ソケットを含むリストをxread引数に渡す「 select 」も試しましたが、selectも最後まで「無意味」に見えます.
Python 2.5 - 2.6 を使用して、Linux と Windows で同じ動作を維持する独自のコードが必要です。
ありがとう。