lewoudar / ws

The simplest websocket cli
https://pyws.readthedocs.io/en/latest/
Apache License 2.0
58 stars 1 forks source link

HandshakeError after run 'ws listen ws://localhost:8000/hello' on macOS #30

Open sangshuduo opened 5 months ago

sangshuduo commented 5 months ago

ws --version ws version 0.1.0

python3 --version Python 3.10.13

`ws listen ws://localhost:8000/hello  ✔  9657  21:58:08 ExceptionGroup: all attempts to connect to localhost:8000 failed (2 sub-exceptions)

The above exception was the direct cause of the following exception:

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/trio_websocket/_impl.py:120 in │ │ open_websocket │ │ │ │ 117 │ async with trio.open_nursery() as new_nursery: │ │ 118 │ │ try: │ │ 119 │ │ │ with trio.fail_after(connect_timeout): │ │ ❱ 120 │ │ │ │ connection = await connect_websocket(new_nursery, host, port, │ │ 121 │ │ │ │ │ resource, use_ssl=use_ssl, subprotocols=subprotocols, │ │ 122 │ │ │ │ │ extra_headers=extra_headers, │ │ 123 │ │ │ │ │ message_queue_size=message_queue_size, │ │ │ │ ╭───────────────────────── locals ──────────────────────────╮ │ │ │ connect_timeout = 5.0 │ │ │ │ disconnect_timeout = 5.0 │ │ │ │ extra_headers = None │ │ │ │ host = 'localhost' │ │ │ │ max_message_size = 1048576 │ │ │ │ message_queue_size = 1 │ │ │ │ new_nursery = <trio.Nursery object at 0x105ddcbb0> │ │ │ │ port = 8000 │ │ │ │ resource = '/hello' │ │ │ │ subprotocols = None │ │ │ │ use_ssl = False │ │ │ ╰───────────────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/trio_websocket/_impl.py:183 in │ │ connect_websocket │ │ │ │ 180 │ logger.debug('Connecting to ws%s://%s:%d%s', │ │ 181 │ │ '' if ssl_context is None else 's', host, port, resource) │ │ 182 │ if ssl_context is None: │ │ ❱ 183 │ │ stream = await trio.open_tcp_stream(host, port) │ │ 184 │ else: │ │ 185 │ │ stream = await trio.open_ssl_over_tcp_stream(host, port, │ │ 186 │ │ │ ssl_context=ssl_context, https_compatible=True) │ │ │ │ ╭───────────────────────── locals ──────────────────────────╮ │ │ │ extra_headers = None │ │ │ │ host = 'localhost' │ │ │ │ max_message_size = 1048576 │ │ │ │ message_queue_size = 1 │ │ │ │ nursery = <trio.Nursery object at 0x105ddcbb0> │ │ │ │ port = 8000 │ │ │ │ resource = '/hello' │ │ │ │ ssl_context = None │ │ │ │ subprotocols = None │ │ │ │ use_ssl = False │ │ │ ╰───────────────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/trio/_highlevel_open_tcp_stream.py:403 │ │ in open_tcp_stream │ │ │ │ 400 │ │ if winning_socket is None: │ │ 401 │ │ │ assert len(oserrors) == len(targets) │ │ 402 │ │ │ msg = f"all attempts to connect to {format_host_port(host, port)} failed" │ │ ❱ 403 │ │ │ raise OSError(msg) from ExceptionGroup(msg, oserrors) │ │ 404 │ │ else: │ │ 405 │ │ │ stream = trio.SocketStream(winning_socket) │ │ 406 │ │ │ open_sockets.remove(winningsocket) │ │ │ │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │ │ │ = '' │ │ │ │ addr = ('127.0.0.1', 8000) │ │ │ │ address_family = <AddressFamily.AF_INET: 2> │ │ │ │ attempt_connect = <function open_tcp_stream..attempt_connect at 0x105dd8700> │ │ │ │ attempt_failed = Event(_tasks=set(), _flag=True) │ │ │ │ happy_eyeballs_delay = 0.25 │ │ │ │ host = 'localhost' │ │ │ │ local_address = None │ │ │ │ msg = 'all attempts to connect to localhost:8000 failed' │ │ │ │ nursery = <trio.Nursery object at 0x105ddc4f0> │ │ │ │ open_sockets = { │ │ │ │ │ <trio.socket.socket [closed] fd=-1, │ │ │ │ family=AddressFamily.AF_INET6, type=SocketKind.SOCK_STREAM, proto=6>, │ │ │ │ │ <trio.socket.socket [closed] fd=-1, family=AddressFamily.AF_INET, │ │ │ │ type=SocketKind.SOCK_STREAM, proto=6> │ │ │ │ } │ │ │ │ oserrors = [ │ │ │ │ │ ConnectionRefusedError(61, "Error connecting to ('::1', 8000, 0, │ │ │ │ 0): Connection refused"), │ │ │ │ │ ConnectionRefusedError(61, "Error connecting to ('127.0.0.1', │ │ │ │ 8000): Connection refused") │ │ │ │ ] │ │ │ │ port = 8000 │ │ │ │ proto = 6 │ │ │ │ socket_type = <SocketKind.SOCK_STREAM: 1> │ │ │ │ targets = [ │ │ │ │ │ ( │ │ │ │ │ │ <AddressFamily.AF_INET6: 30>, │ │ │ │ │ │ <SocketKind.SOCK_STREAM: 1>, │ │ │ │ │ │ 6, │ │ │ │ │ │ '', │ │ │ │ │ │ ('::1', 8000, 0, 0) │ │ │ │ │ ), │ │ │ │ │ ( │ │ │ │ │ │ <AddressFamily.AF_INET: 2>, │ │ │ │ │ │ <SocketKind.SOCK_STREAM: 1>, │ │ │ │ │ │ 6, │ │ │ │ │ │ '', │ │ │ │ │ │ ('127.0.0.1', 8000) │ │ │ │ │ ) │ │ │ │ ] │ │ │ │ winning_socket = None │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ OSError: all attempts to connect to localhost:8000 failed

The above exception was the direct cause of the following exception:

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮ │ /Users/sangshuduo/anaconda3/bin/ws:8 in │ │ │ │ 5 from ws.main import cli │ │ 6 if name == 'main': │ │ 7 │ sys.argv[0] = re.sub(r'(-script.pyw|.exe)?$', '', sys.argv[0]) │ │ ❱ 8 │ sys.exit(cli()) │ │ 9 │ │ │ │ ╭────────────────────────────────── locals ───────────────────────────────────╮ │ │ │ cli = │ │ │ │ re = <module 're' from '/Users/sangshuduo/anaconda3/lib/python3.10/re.py'> │ │ │ │ sys = <module 'sys' (built-in)> │ │ │ ╰─────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/click/core.py:1157 in call │ │ │ │ 1154 │ │ │ 1155 │ def call(self, *args: t.Any, kwargs: t.Any) -> t.Any: │ │ 1156 │ │ """Alias for :meth:main.""" │ │ ❱ 1157 │ │ return self.main(*args, kwargs) │ │ 1158 │ │ 1159 │ │ 1160 class Command(BaseCommand): │ │ │ │ ╭──────── locals ─────────╮ │ │ │ args = () │ │ │ │ kwargs = {} │ │ │ │ self = │ │ │ ╰─────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/click/core.py:1078 in main │ │ │ │ 1075 │ │ try: │ │ 1076 │ │ │ try: │ │ 1077 │ │ │ │ with self.make_context(prog_name, args, extra) as ctx: │ │ ❱ 1078 │ │ │ │ │ rv = self.invoke(ctx) │ │ 1079 │ │ │ │ │ if not standalone_mode: │ │ 1080 │ │ │ │ │ │ return rv │ │ 1081 │ │ │ │ │ # it's not safe to ctx.exit(rv) here! │ │ │ │ ╭───────────────────────────── locals ─────────────────────────────╮ │ │ │ args = ['listen', 'ws://localhost:8000/hello'] │ │ │ │ complete_var = None │ │ │ │ ctx = <click.core.Context object at 0x1027953f0> │ │ │ │ extra = {} │ │ │ │ prog_name = 'ws' │ │ │ │ self = │ │ │ │ standalone_mode = True │ │ │ │ windows_expand_args = True │ │ │ ╰──────────────────────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/click/core.py:1688 in invoke │ │ │ │ 1685 │ │ │ │ super().invoke(ctx) │ │ 1686 │ │ │ │ sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) │ │ 1687 │ │ │ │ with sub_ctx: │ │ ❱ 1688 │ │ │ │ │ return _process_result(sub_ctx.command.invoke(sub_ctx)) │ │ 1689 │ │ │ │ 1690 │ │ # In chain mode we create the contexts step by step, but after the │ │ 1691 │ │ # base command has been invoked. Because at that point we do not │ │ │ │ ╭───────────────────────────────────────── locals ─────────────────────────────────────────╮ │ │ │ _process_result = <function MultiCommand.invoke.._process_result at 0x10265fd90> │ │ │ │ args = [] │ │ │ │ cmd = │ │ │ │ cmd_name = 'listen' │ │ │ │ ctx = <click.core.Context object at 0x1027953f0> │ │ │ │ self = │ │ │ │ sub_ctx = <click.core.Context object at 0x105dddd80> │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/click/core.py:1434 in invoke │ │ │ │ 1431 │ │ │ echo(style(message, fg="red"), err=True) │ │ 1432 │ │ │ │ 1433 │ │ if self.callback is not None: │ │ ❱ 1434 │ │ │ return ctx.invoke(self.callback, *ctx.params) │ │ 1435 │ │ │ 1436 │ def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: │ │ 1437 │ │ """Return a list of completions for the incomplete value. Looks │ │ │ │ ╭───────────────────── locals ──────────────────────╮ │ │ │ ctx = <click.core.Context object at 0x105dddd80> │ │ │ │ self = │ │ │ ╰───────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/click/core.py:783 in invoke │ │ │ │ 780 │ │ │ │ 781 │ │ with augment_usage_errors(self): │ │ 782 │ │ │ with ctx: │ │ ❱ 783 │ │ │ │ return callback(args, kwargs) │ │ 784 │ │ │ 785 │ def forward( │ │ 786 │ │ self, cmd: "Command", *args: t.Any, **kwargs: t.Any # noqa: B902 │ │ │ │ ╭──────────────────────────── locals ─────────────────────────────╮ │ │ │ _Context__callback = <function listen at 0x105764d30> │ │ │ │ _Context__self = <click.core.Context object at 0x105dddd80> │ │ │ │ args = () │ │ │ │ ctx = <click.core.Context object at 0x105dddd80> │ │ │ │ kwargs = { │ │ │ │ │ 'url': 'ws://localhost:8000/hello', │ │ │ │ │ 'is_json': False, │ │ │ │ │ 'duration': None, │ │ │ │ │ 'filename': None │ │ │ │ } │ │ │ ╰─────────────────────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/ws/commands/listen.py:76 in listen │ │ │ │ 73 @filename_option │ │ 74 def listen(url: str, is_json: bool, duration: float, filename: str): │ │ 75 │ """Listens messages on a given URL.""" │ │ ❱ 76 │ trio.run(main, url, is_json, duration, filename) │ │ 77 │ │ │ │ ╭──────────────── locals ────────────────╮ │ │ │ duration = None │ │ │ │ filename = None │ │ │ │ is_json = False │ │ │ │ url = 'ws://localhost:8000/hello' │ │ │ ╰────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/trio/_core/_run.py:2275 in run │ │ │ │ 2272 │ if isinstance(runner.main_task_outcome, Value): │ │ 2273 │ │ return cast(RetT, runner.main_task_outcome.value) │ │ 2274 │ elif isinstance(runner.main_task_outcome, Error): │ │ ❱ 2275 │ │ raise runner.main_task_outcome.error │ │ 2276 │ else: # pragma: no cover │ │ 2277 │ │ raise AssertionError(runner.main_task_outcome) │ │ 2278 │ │ │ │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │ │ │ args = ( │ │ │ │ │ 'ws://localhost:8000/hello', │ │ │ │ │ False, │ │ │ │ │ None, │ │ │ │ │ None │ │ │ │ ) │ │ │ │ async_fn = <function main at 0x105764b80> │ │ │ │ clock = None │ │ │ │ gen = <generator object unrolled_run at 0x105df06d0> │ │ │ │ instruments = () │ │ │ │ next_send = [] │ │ │ │ prev_library = None │ │ │ │ restrict_keyboard_interrupt_to_checkpoints = False │ │ │ │ runner = Runner( │ │ │ │ │ clock=SystemClock( │ │ │ │ │ │ offset=162718.46147645527 │ │ │ │ │ ), │ │ │ │ │ instruments={'_all': {}}, │ │ │ │ │ io_manager=KqueueIOManager( │ │ │ │ │ │ _kqueue=<select.kqueue object at │ │ │ │ 0x1025ffbf0>, │ │ │ │ │ │ _registered={}, │ │ │ │ │ │ │ │ │ │ _force_wakeup=<trio._core._wakeup_socketpair.W… │ │ │ │ object at 0x105ddce20>, │ │ │ │ │ │ _force_wakeup_fd=4 │ │ │ │ │ ), │ │ │ │ │ ki_manager=KIManager(handler=None), │ │ │ │ │ strict_exception_groups=False, │ │ │ │ │ _locals={ │ │ │ │ │ │ : │ │ │ │ <trio.CapacityLimiter at 0x105dde710, 0/40 with │ │ │ │ 0 waiting> │ │ │ │ │ }, │ │ │ │ │ runq=deque(), │ │ │ │ │ tasks=set(), │ │ │ │ │ deadlines=Deadlines(_heap=[], _active=0), │ │ │ │ │ init_task=Task( │ │ │ │ │ │ _parent_nursery=None, │ │ │ │ │ │ coro=<coroutine object Runner.init at │ │ │ │ 0x105df0740>, │ │ │ │ │ │ _runner=..., │ │ │ │ │ │ name='', │ │ │ │ │ │ context=<_contextvars.Context object at │ │ │ │ 0x105deaa80>, │ │ │ │ │ │ _counter=0, │ │ │ │ │ │ _next_send_fn=None, │ │ │ │ │ │ _next_send=None, │ │ │ │ │ │ _abort_func=None, │ │ │ │ │ │ custom_sleep_data=None, │ │ │ │ │ │ _child_nurseries=[], │ │ │ │ │ │ _eventual_parent_nursery=None, │ │ │ │ │ │ _cancel_points=3, │ │ │ │ │ │ _schedule_points=4 │ │ │ │ │ ), │ │ │ │ │ system_nursery=<trio.Nursery object at │ │ │ │ 0x105dde1d0>, │ │ │ │ │ system_context=<_contextvars.Context object │ │ │ │ at 0x105dea180>, │ │ │ │ │ main_task=Task( │ │ │ │ │ │ _parent_nursery=<trio.Nursery object at │ │ │ │ 0x105dde260>, │ │ │ │ │ │ coro=<coroutine object main at │ │ │ │ 0x105df07b0>, │ │ │ │ │ │ _runner=..., │ │ │ │ │ │ name='ws.commands.listen.main', │ │ │ │ │ │ context=<_contextvars.Context object at │ │ │ │ 0x105deac80>, │ │ │ │ │ │ _counter=1, │ │ │ │ │ │ _next_send_fn=None, │ │ │ │ │ │ _next_send=None, │ │ │ │ │ │ _abort_func=None, │ │ │ │ │ │ custom_sleep_data=None, │ │ │ │ │ │ _child_nurseries=[], │ │ │ │ │ │ _eventual_parent_nursery=None, │ │ │ │ │ │ _cancel_points=1, │ │ │ │ │ │ _schedule_points=1 │ │ │ │ │ ), │ │ │ │ │ main_task_outcome=Error( │ │ │ │ │ │ _unwrapped=False, │ │ │ │ │ │ error=HandshakeError() │ │ │ │ │ ), │ │ │ │ │ entry_queue=EntryQueue( │ │ │ │ │ │ queue=deque(), │ │ │ │ │ │ idempotent_queue={}, │ │ │ │ │ │ │ │ │ │ wakeup=<trio._core._wakeup_socketpair.WakeupSo… │ │ │ │ object at 0x105ddd300>, │ │ │ │ │ │ done=True, │ │ │ │ │ │ lock=<unlocked _thread.RLock object │ │ │ │ owner=0 count=0 at 0x105dea6c0> │ │ │ │ │ ), │ │ │ │ │ trio_token=TrioToken( │ │ │ │ │ │ _reentry_queue=EntryQueue( │ │ │ │ │ │ │ queue=deque(), │ │ │ │ │ │ │ idempotent_queue={}, │ │ │ │ │ │ │ │ │ │ │ wakeup=<trio._core._wakeup_socketpair.WakeupSo… │ │ │ │ object at 0x105ddd300>, │ │ │ │ │ │ │ done=True, │ │ │ │ │ │ │ lock=<unlocked _thread.RLock object │ │ │ │ owner=0 count=0 at 0x105dea6c0> │ │ │ │ │ │ ) │ │ │ │ │ ), │ │ │ │ │ asyncgens=AsyncGenerators( │ │ │ │ │ │ alive=set(), │ │ │ │ │ │ trailing_needs_finalize=set(), │ │ │ │ │ │ │ │ │ │ prev_hooks=asyncgen_hooks(firstiter=None, │ │ │ │ finalizer=None) │ │ │ │ │ ), │ │ │ │ │ clock_autojump_threshold=inf, │ │ │ │ │ is_guest=False, │ │ │ │ │ guest_tick_scheduled=False, │ │ │ │ │ ki_pending=False, │ │ │ │ │ waiting_for_idle=SortedDict({}) │ │ │ │ ) │ │ │ │ strict_exception_groups = False │ │ │ │ timeout = 0 │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/ws/commands/listen.py:60 in main │ │ │ │ 57 │ │ 58 │ │ 59 async def main(url: str, is_json: bool, duration: Optional[float] = None, filename: Opti │ │ ❱ 60 │ async with trio.open_nursery() as nursery: │ │ 61 │ │ nursery.start_soon(function_runner, nursery.cancel_scope, listen_messages, url, │ │ 62 │ │ nursery.start_soon(signal_handler, nursery.cancel_scope) │ │ 63 │ │ nursery.start_soon(sleep_until, nursery.cancel_scope, duration) │ │ │ │ ╭────────────────────────────── locals ──────────────────────────────╮ │ │ │ @TRIO_KI_PROTECTION_ENABLED = False │ │ │ │ duration = None │ │ │ │ filename = None │ │ │ │ is_json = False │ │ │ │ nursery = <trio.Nursery object at 0x105ddd4e0> │ │ │ │ url = 'ws://localhost:8000/hello' │ │ │ ╰────────────────────────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/trio/_core/_run.py:971 in aexit │ │ │ │ 968 │ │ │ # allow us to encapsulate this context fixup. │ │ 969 │ │ │ old_context = combined_error_from_nursery.context │ │ 970 │ │ │ try: │ │ ❱ 971 │ │ │ │ raise combined_error_fromnursery │ │ 972 │ │ │ finally: │ │ 973 │ │ │ │ , value, _ = sys.exc_info() │ │ 974 │ │ │ │ assert value is combined_error_from_nursery │ │ │ │ ╭───────────────────────────────────────── locals ──────────────────────────────────────────╮ │ │ │ @TRIO_KI_PROTECTION_ENABLED = True │ │ │ │ etype = None │ │ │ │ exc = None │ │ │ │ old_context = OSError('all attempts to connect to localhost:8000 failed') │ │ │ │ self = NurseryManager(strict_exception_groups=False) │ │ │ │ tb = None │ │ │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/ws/utils/io.py:22 in function_runner │ │ │ │ 19 │ │ 20 │ │ 21 async def function_runner(scope: trio.CancelScope, function: Callable, args: Any) -> No │ │ ❱ 22 │ await function(args) │ │ 23 │ # noinspection PyAsyncCall │ │ 24 │ scope.cancel() │ │ 25 │ │ │ │ ╭───────────────────────────────── locals ─────────────────────────────────╮ │ │ │ @TRIO_KI_PROTECTION_ENABLED = False │ │ │ │ args = ('ws://localhost:8000/hello', False, None) │ │ │ │ function = <function listen_messages at 0x105764af0> │ │ │ │ scope = CancelScope( │ │ │ │ │ _cancel_status=None, │ │ │ │ │ _has_been_entered=True, │ │ │ │ │ _registered_deadline=inf, │ │ │ │ │ _cancel_called=True, │ │ │ │ │ cancelled_caught=True, │ │ │ │ │ _deadline=inf, │ │ │ │ │ _shield=False │ │ │ │ ) │ │ │ ╰──────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/ws/commands/listen.py:47 in │ │ listen_messages │ │ │ │ 44 async def listen_messages(url: str, is_json: bool, filename: Optional[str] = None) -> No │ │ 45 │ configure_console_recording(console, get_settings(), filename) │ │ 46 │ │ │ ❱ 47 │ async with websocket_client(url) as client: │ │ 48 │ │ while True: │ │ 49 │ │ │ message = await client.get_message() │ │ 50 │ │ │ is_bytes = isinstance(message, bytes) │ │ │ │ ╭──────────────── locals ────────────────╮ │ │ │ filename = None │ │ │ │ is_json = False │ │ │ │ url = 'ws://localhost:8000/hello' │ │ │ ╰────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/contextlib.py:199 in aenter │ │ │ │ 196 │ │ # they are only needed for recreation, which is not possible anymore │ │ 197 │ │ del self.args, self.kwds, self.func │ │ 198 │ │ try: │ │ ❱ 199 │ │ │ return await anext(self.gen) │ │ 200 │ │ except StopAsyncIteration: │ │ 201 │ │ │ raise RuntimeError("generator didn't yield") from None │ │ 202 │ │ │ │ ╭──────────────────────────────── locals ─────────────────────────────────╮ │ │ │ self = <contextlib._AsyncGeneratorContextManager object at 0x105ddc850> │ │ │ ╰─────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/ws/client.py:92 in websocket_client │ │ │ │ 89 │ ) │ │ 90 │ │ │ 91 │ try: │ │ ❱ 92 │ │ async with open_websocket_url(url, ssl_context=ssl_context, **arguments) as ws: │ │ 93 │ │ │ yield ws │ │ 94 │ except ConnectionTimeout: │ │ 95 │ │ console.print(f'[error]Unable to connect to {url}') │ │ │ │ ╭──────────────────── locals ────────────────────╮ │ │ │ arguments = { │ │ │ │ │ 'connect_timeout': 5.0, │ │ │ │ │ 'disconnect_timeout': 5.0, │ │ │ │ │ 'message_queue_size': 1, │ │ │ │ │ 'max_message_size': 1048576, │ │ │ │ │ 'extra_headers': None │ │ │ │ } │ │ │ │ settings = Settings( │ │ │ │ │ connect_timeout=5.0, │ │ │ │ │ disconnect_timeout=5.0, │ │ │ │ │ response_timeout=5.0, │ │ │ │ │ message_queue_size=1, │ │ │ │ │ max_message_size=1048576, │ │ │ │ │ extra_headers=None, │ │ │ │ │ terminal_width=180, │ │ │ │ │ tls_ca_file=None, │ │ │ │ │ tls_certificate_file=None, │ │ │ │ │ tls_key_file=None, │ │ │ │ │ tls_password=None │ │ │ │ ) │ │ │ │ ssl_context = None │ │ │ │ url = 'ws://localhost:8000/hello' │ │ │ ╰────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/contextlib.py:199 in aenter │ │ │ │ 196 │ │ # they are only needed for recreation, which is not possible anymore │ │ 197 │ │ del self.args, self.kwds, self.func │ │ 198 │ │ try: │ │ ❱ 199 │ │ │ return await anext(self.gen) │ │ 200 │ │ except StopAsyncIteration: │ │ 201 │ │ │ raise RuntimeError("generator didn't yield") from None │ │ 202 │ │ │ │ ╭──────────────────────────────── locals ─────────────────────────────────╮ │ │ │ self = <contextlib._AsyncGeneratorContextManager object at 0x105ddc8b0> │ │ │ ╰─────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /Users/sangshuduo/anaconda3/lib/python3.10/site-packages/trio_websocket/_impl.py:128 in │ │ open_websocket │ │ │ │ 125 │ │ except trio.TooSlowError: │ │ 126 │ │ │ raise ConnectionTimeout from None │ │ 127 │ │ except OSError as e: │ │ ❱ 128 │ │ │ raise HandshakeError from e │ │ 129 │ │ try: │ │ 130 │ │ │ yield connection │ │ 131 │ │ finally: │ │ │ │ ╭───────────────────────── locals ──────────────────────────╮ │ │ │ connect_timeout = 5.0 │ │ │ │ disconnect_timeout = 5.0 │ │ │ │ extra_headers = None │ │ │ │ host = 'localhost' │ │ │ │ max_message_size = 1048576 │ │ │ │ message_queue_size = 1 │ │ │ │ new_nursery = <trio.Nursery object at 0x105ddcbb0> │ │ │ │ port = 8000 │ │ │ │ resource = '/hello' │ │ │ │ subprotocols = None │ │ │ │ use_ssl = False │ │ │ ╰───────────────────────────────────────────────────────────╯ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ HandshakeError`

lewoudar commented 5 months ago

Hello, First of all, are you sure your server was started before the client run? Did you try to upgrade the websocket version to the latest one?

sangshuduo commented 5 months ago

Maybe I confuse the difference between echo-server and listen command. Since I can't see any response from echo-server when I send a text to the echo-server. However, even when I ran echo-server first, then run ws listen it still exit with ConnectionClosed error. Could you please introduce a typical scenario of how to set up a server can respond explicitly to the screen after receiving the text from a client? Thanks.