- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个简单的命令和控制服务器 server.py
(完全不安全 - 不要使用),一个被动客户端 update_client.py
和另一个可以发送命令 update_commander.py
。在 http://0.0.0.0:8080/ 处有一个 http 端点其中列出了连接的客户端。当 update_commander.py
脚本退出时,它的客户端会被正确清理。当 update_client.py
断开连接时,服务器没有注意到断开连接,并且在 update_commander.py
发送的进一步消息上,我收到错误 socket.send()引发异常。
对于每个幽灵客户端连接。清理代码标记为### CLEANUP CODE ###
我觉得我应该做的是在尝试发送到套接字但没有引发异常时捕获错误,只是向标准输出发送一条消息。
server.py
import uuid
import asyncio
import aiohttp
from aiohttp import web
class Client(object):
def __init__(self):
self.websocket = None
self.name = None
class ClientList(web.View):
async def get(self):
clients = self.request.app['clients']
client_list = [client.name for name, client in clients.items()]
txt = ", ".join(client_list)
return web.Response(text=txt)
class WebSocket(web.View):
async def get(self):
ws = web.WebSocketResponse()
await ws.prepare(self.request)
# session = await get_session(self.request)
# user = User(self.request.db, {'id': session.get('user')})
# login = await user.get_login()
login = str(uuid.uuid4())
client = Client()
client.name = login
client.websocket = ws
self.request.app['clients'][client.name] = client
print('%s connected.' % login)
for _ws in [c.websocket for name, c in self.request.app['clients'].items()]:
_ws.send_str('%s joined' % login)
async for msg in ws:
if msg.tp == aiohttp.WSMsgType.text:
if msg.data == 'close':
await ws.close()
else:
# do something here like save it
print('%s sent: %s' % (login, msg.data))
# Send message to all clients other clients
for _ws in [c.websocket for name, c in self.request.app['clients'].items()]:
try:
_ws.send_str('(%s) %s' % (login, msg.data))
asyncio.sleep(0)
except:
print(ws.exception())
elif msg.tp == aiohttp.WSMsgType.error:
print('ws connection closed with exception %s' % ws.exception())
### CLEANUP CODE ###
await client.websocket.close()
del self.request.app['clients'][client.name]
for _ws in [c.websocket for name, c in self.request.app['clients'].items()]:
_ws.send_str('%s disconected' % login)
print('%s disconnected' % login)
return ws
routes = [
('GET', '/', ClientList, 'main'),
('GET', '/ws', WebSocket, 'chat'),
]
app = web.Application()
for route in routes:
app.router.add_route(route[0], route[1], route[2], name=route[3])
app['clients'] = {}
web.run_app(app)
指挥官.py
import asyncio
import aiohttp
import os
HOST = os.getenv('HOST', '0.0.0.0')
PORT = int(os.getenv('PORT', 8080))
URL = f'http://{HOST}:{PORT}/ws'
async def main():
session = aiohttp.ClientSession()
async with session.ws_connect(URL) as ws:
await prompt_and_send(ws)
async for msg in ws:
print('Message received from server:', msg.data)
await prompt_and_send(ws)
if msg.type in (aiohttp.WSMsgType.CLOSED,
aiohttp.WSMsgType.ERROR):
break
async def prompt_and_send(ws):
new_msg_to_send = input('Type a message to send to the server: ')
if new_msg_to_send == 'exit':
print('Exiting!')
raise SystemExit(0)
await ws.send_str(new_msg_to_send)
if __name__ == '__main__':
print('Type "exit" to quit')
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
客户端.py
import aiohttp
import asyncio
import os
import time
import logging
import sys
logging.basicConfig(
level=logging.DEBUG,
format='%(name)s: %(message)s',
stream=sys.stderr,
)
log = logging.getLogger('main')
HOST = os.getenv('HOST', '0.0.0.0')
PORT = int(os.getenv('PORT', 8080))
URL = f'http://{HOST}:{PORT}/ws'
async def callback(msg):
if msg == 'time':
#ws.send_str(time.time())
print(msg)
else:
print(msg)
async def main():
session = aiohttp.ClientSession()
async with session.ws_connect(URL) as ws:
async for msg in ws:
if msg.type == aiohttp.WSMsgType.TEXT:
await callback(msg.data)
elif msg.type == aiohttp.WSMsgType.CLOSED:
print("CLOSED")
break
elif msg.type == aiohttp.WSMsgType.ERROR:
print("error")
break
if __name__ == '__main__':
loop = asyncio.get_event_loop()
tasks = loop.run_until_complete(main())
try:
loop.run_forever()
except KeyboardInterrupt as e:
print("Caught keyboard interrupt. Canceling tasks...")
tasks.cancel()
loop.run_forever()
finally:
log.debug('closing server')
loop.run_until_complete(loop.shutdown_asyncgens()) # python 3.6 only
log.debug('closing event loop')
loop.close()
最佳答案
因此,有时仅向其他人阐明问题会有所帮助。我通过像这样在 try/finally 中包装整个 async for msg in ws:
来修复它。
try:
async for msg in ws:
if msg.tp == aiohttp.WSMsgType.text:
if msg.data == 'close':
await ws.close()
else:
# do something here like save it
print('%s sent: %s' % (login, msg.data))
# Send message to all clients other clients
for _ws in [c.websocket for name, c in self.request.app['clients'].items()]:
_ws.send_str('(%s) %s' % (login, msg.data))
elif msg.tp == aiohttp.WSMsgType.error:
print('ws connection closed with exception %s' % ws.exception())
finally:
await client.websocket.close()
del self.request.app['clients'][client.name]
for _ws in [c.websocket for name, c in self.request.app['clients'].items()]:
_ws.send_str('%s disconected' % login)
print('%s disconnected' % login)
关于python - 当客户端不干净地退出时,如何检测服务器上 Python aiohttp web 套接字的关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48695294/
我想要一个类似于 django runserver 所做的重新加载。 如果我更改 python 文件,我希望应用程序重新加载。我已经安装了 aiohttp-devtools 并使用 adev runs
我在使用 RouteTableDef 时遇到问题。 有一些项目的路由结构如下: 1) 有文件route.py。 路线.py from aiohttp import web routes = web.R
我有一些代码对某些 API 进行请求序列。我想为所有人设置通用日志记录,我该如何设置? 假设我的代码是这样的 import aiohttp import asyncio async def fetch
您能否就以下方面提出建议? 在 localhost:8900 上有 aiohttp 服务器在运行 当我从 python 发出类似(使用 python2 模块请求)的请求时 requests.get("
每当我对使用 asyncio 和 aiohttp 访问的 API 执行超过 200 个请求时,我都会收到 aiohttp client_exception.ServerDisconnectedErro
在我正在开发的爬虫中。它使用 pycurl multi 发出请求。 如果我改用aiohttp,我可以期待什么样的效率提升? 怀疑让我怀疑潜在的改进,因为 python 有 GIL。大部分时间都花在等待
我在尝试使用 azure 测试聊天机器人时遇到一些问题: 我使用 github actions 在 azure web 应用程序上部署了我的机器人,一切都很顺利。但是当我尝试测试我的聊天机器人时,没有
我在尝试使用 azure 测试聊天机器人时遇到一些问题: 我使用 github actions 在 azure web 应用程序上部署了我的机器人,一切都很顺利。但是当我尝试测试我的聊天机器人时,没有
我想知道如何从 aiohttp post 方法获取当前的上传步骤。通常我会使用 get 方法在循环中拉取当前步骤,但如果主机不响应当前上传步骤,这将不起作用。那么有可能得到当前步骤吗?诸如“从 xx%
我目前正在用 aiohttp 做我的第一个“婴儿学步” (来自 requests 模块)。 我尝试稍微简化请求,这样我就不必在主模块中为每个请求使用上下文管理器。 因此我尝试了这个: async de
tl;dr:如何最大化可以并行发送的 http 请求数量? 我正在使用 aiohttp 库从多个网址获取数据。我正在测试它的性能,并且观察到该过程中的某个地方存在瓶颈,一次运行更多的网址并没有帮助。
目前我正在执行以下操作来获取当前正在运行的应用程序 async def handler(request): app = request.app 是否有其他方法来获取当前正在运行的应用程序?考虑
首先是代码: import random import asyncio from aiohttp import ClientSession import csv headers =[] def ext
我的 aiohttp 中间件获取函数作为参数,而不是已传递给路由的绑定(bind)方法。如何解释这种行为?如何避免这种情况? class AsyncHttpServer: def __init
我正在尝试在 aiohttp 处理程序中启动后台长时间任务: from aiohttp import web import time import asyncio async def one(requ
我正在测试 aiohttp 和 asyncio。我希望相同的事件循环具有套接字、http 服务器、http 客户端。 我正在使用此示例代码: @routes.get('/') async def he
#!/usr/bin/env python3.5 import asyncio import aiohttp url = "http://eniig.dk" async def main():
考虑以下代码: from aiohttp_mako import template def authorize(): def wrapper(func): @asyncio.c
我正在编写一个网络爬虫,它为许多不同的域运行并行提取。我想限制每秒向每个单独的域发出的请求数,但我不关心打开的连接总数或每秒的总请求数跨越所有领域。 我想最大限度地提高打开的连接数和每秒请求数,同时限
我需要将 sub_app 添加到 sub_app。这是我的代码 app = web.Application() subapp = web.Application() subapp.router.add
我是一名优秀的程序员,十分优秀!