![](/img/trans.png)
[英]Python3 and asyncio: how to implement websocket server as asyncio instance?
[英]How to implement timeout in asyncio server?
下面是一個簡單的echo服務器。 但如果客戶端10秒鍾沒有發送任何內容,我想關閉連接。
import asyncio
async def process(reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
print("awaiting for data")
line = await reader.readline()
print(f"received {line}")
writer.write(line)
print(f"sent {line}")
await writer.drain()
print(f"Drained")
async def timeout(task: asyncio.Task, duration):
print("timeout started")
await asyncio.sleep(duration)
print("client unresponsive, cancelling")
task.cancel()
print("task cancelled")
async def new_session(reader, writer):
print("new session started")
task = asyncio.create_task(process(reader, writer))
timer = asyncio.create_task(timeout(task, 10))
await task
print("task complete")
timer.cancel()
print("timer cancelled")
writer.close()
print("writer closed")
async def a_main():
server = await asyncio.start_server(new_session, port=8088)
await server.serve_forever()
if __name__ == '__main__':
asyncio.run(a_main())
如果客戶端發送消息,它可以正常工作。 但另一種情況是,當客戶端保持沉默時,它不起作用
當客戶端發送消息時:
new session started
awaiting for data
timeout started
received b'slkdfjsdlkfj\r\n'
sent b'slkdfjsdlkfj\r\n'
Drained
task complete
timer cancelled
writer closed
打開連接后客戶端靜默
new session started
awaiting for data
timeout started
client unresponsive, cancelling
task cancelled
沒有task complete
, timer cancelled
, writer closed
。
更新
找出問題,看起來任務實際上已被取消,但異常被忽略,通過捕獲CancelledError
解決了問題
async def new_session(reader, writer):
print("new session started")
task = asyncio.create_task(process(reader, writer))
timer = asyncio.create_task(timeout(task, 10))
try:
await task
except asyncio.CancelledError:
print(f"Task took too long and was cancelled by timer")
print("task complete")
timer.cancel()
print("timer cancelled")
writer.close()
print("writer closed")
第二部分仍然存在。 有沒有更好的方法來實現超時?
UPDATE2
使用wait_for
完成代碼。 不再需要超時代碼。 檢查以下解決方案 :
async def new_session(reader, writer):
print("new session started")
try:
await asyncio.wait_for(process(reader, writer), timeout=5)
except asyncio.TimeoutError as te:
print(f'time is up!{te}')
finally:
writer.close()
print("writer closed")
我在建立連接時使用以下代碼。 我建議你的代碼使用wait_for。
fut = asyncio.open_connection( self.host, self.port, loop=self.loop )
try:
r, w = await asyncio.wait_for(fut, timeout=self.connection_timeout)
except asyncio.TimeoutError:
pass
有沒有更好的方法來實現超時?
您可以使用asyncio.wait_for
而不是timeout
。 它有類似的語義,但已經附帶asyncio。 此外,您可以等待將來返回以檢測是否已發生超時。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.