接続ごとに新しいスレッドを開くスレッド化されたPythonソケットサーバーがあります。
スレッドは、質問と回答に基づく非常に単純なコミュニケーションです。基本的に、クライアントは最初のデータ送信を送信します。サーバーは、送信に対して処理を行う外部アプリを実行し、サーバーが返信する応答を返します。クライアントが切断されるまで、ループが再開されます。
クライアントが携帯電話を使用しているため、接続が不安定になり、開いているスレッドが接続されなくなり、ループがrecvで始まるため、この方法で接続が失われた場合に切断するのはかなり困難です。
接続がまだ有効かどうかをテストするために、recvの前に送信を追加することを考えていましたが、クライアントが5秒ごとにのみデータストリームを送信するため、フェイルセーフ送信後にクライアントが切断した場合、これはまったく役に立たない可能性があります。
私は、recvが時々壊れることに気づきましたが、常にではありません。そのような場合、リソースを使用しているゾンビスレッドが残ります。
また、これは私のシステムがDOS化されるための確かな脆弱性である可能性があります。私は木曜日からこれのために何かを見つけようとしてPythonマニュアルとGoogledを調べましたが、私が見つけたほとんどのものはクライアントと非ブロッキングモードに関連しています。
誰かが私をこの問題を解決するための良い方法に向けて正しい方向に向けることができますか?
コードサンプル:
リスナー:
serversocket = socket(AF_INET, SOCK_STREAM)
serversocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
serversocket.bind(addr)
serversocket.listen(2)
logg("Binded to port: " + str(port))
# Listening Loop
while 1:
clientsocket, clientaddr = serversocket.accept()
threading.Thread(target=handler, args=(clientsocket, clientaddr,port,)).start()
# This is useless as it will never get here
serversocket.close()
ハンドラ:
# Socket connection handler (Threaded)
def handler(clientsocket, clientaddr, port):
clientsocket.settimeout(15)
# Loop till client closes connection or connection drops
while 1:
stream = ''
while 1:
ending = stream[-6:] # get stream ending
if ending == '.$$$$.':
break
try:
data = clientsocket.recv(1)
except:
sys.exit()
if not data:
sys.exit()
# this is the usual point where thread is closed when a client closes connection normally
stream += data
# Clear the line ending
stream = base64.b64encode(stream[:-6])
# Send data to be processed
re = getreply(stream)
# Send response to client
try:
clientsocket.send(re + str('.$$$$.'))
except:
sys.exit()
ご覧のとおり、接続に失敗した場合に少なくとも1つは終了をトリガーする必要がありますが、そうでない場合もある3つの条件があります。