FAQ
***

Note:

  Many questions asked in "websockets"' issue tracker are actually
  about "asyncio". Python's documentation about developing with
  asyncio is a good complement.


Server side
===========


Why does the server close the connection after processing one message?
----------------------------------------------------------------------

Your connection handler exits after processing one message. Write a
loop to process multiple messages.

For example, if your handler looks like this:

   async def handler(websocket, path):
       print(websocket.recv())

change it like this:

   async def handler(websocket, path):
       async for message in websocket:
           print(message)

*Don't feel bad if this happens to you — it's the most common question
in websockets' issue tracker :-)*


Why can only one client connect at a time?
------------------------------------------

Your connection handler blocks the event loop. Look for blocking
calls. Any call that may take some time must be asynchronous.

For example, if you have:

   async def handler(websocket, path):
       time.sleep(1)

change it to:

   async def handler(websocket, path):
       await asyncio.sleep(1)

This is part of learning asyncio. It isn't specific to websockets.

See also Python's documentation about running blocking code.


How can I pass additional arguments to the connection handler?
--------------------------------------------------------------

You can bind additional arguments to the connection handler with
"functools.partial()":

   import asyncio
   import functools
   import websockets

   async def handler(websocket, path, extra_argument):
       ...

   bound_handler = functools.partial(handler, extra_argument='spam')
   start_server = websockets.serve(bound_handler, ...)

Another way to achieve this result is to define the "handler"
coroutine in a scope where the "extra_argument" variable exists
instead of injecting it through an argument.


How do I get access HTTP headers, for example cookies?
------------------------------------------------------

To access HTTP headers during the WebSocket handshake, you can
override "process_request":

   async def process_request(self, path, request_headers):
       cookies = request_header["Cookie"]

Once the connection is established, they're available in
"request_headers":

   async def handler(websocket, path):
       cookies = websocket.request_headers["Cookie"]


How do I get the IP address of the client connecting to my server?
------------------------------------------------------------------

It's available in "remote_address":

   async def handler(websocket, path):
       remote_ip = websocket.remote_address[0]


How do I set which IP addresses my server listens to?
-----------------------------------------------------

Look at the "host" argument of "create_server()".

"serve()" accepts the same arguments as "create_server()".


How do I close a connection properly?
-------------------------------------

websockets takes care of closing the connection when the handler
exits.


How do I run a HTTP server and WebSocket server on the same port?
-----------------------------------------------------------------

This isn't supported.

Providing a HTTP server is out of scope for websockets. It only aims
at providing a WebSocket server.

There's limited support for returning HTTP responses with the
"process_request" hook. If you need more, pick a HTTP server and run
it separately.


Client side
===========


How do I close a connection properly?
-------------------------------------

The easiest is to use "connect()" as a context manager:

   async with connect(...) as websocket:
       ...


How do I reconnect automatically when the connection drops?
-----------------------------------------------------------

See issue 414.


How do I stop a client that is continuously processing messages?
----------------------------------------------------------------

You can close the connection.

Here's an example that terminates cleanly when it receives SIGTERM on
Unix:

   #!/usr/bin/env python

   import asyncio
   import signal
   import websockets

   async def client():
       uri = "ws://localhost:8765"
       async with websockets.connect(uri) as websocket:
           # Close the connection when receiving SIGTERM.
           loop = asyncio.get_event_loop()
           loop.add_signal_handler(
               signal.SIGTERM, loop.create_task, websocket.close())

           # Process messages received on the connection.
           async for message in websocket:
               ...

   asyncio.get_event_loop().run_until_complete(client())


How do I disable TLS/SSL certificate verification?
--------------------------------------------------

Look at the "ssl" argument of "create_connection()".

"connect()" accepts the same arguments as "create_connection()".


Both sides
==========


How do I do two things in parallel? How do I integrate with another coroutine?
------------------------------------------------------------------------------

You must start two tasks, which the event loop will run concurrently.
You can achieve this with "asyncio.gather()" or "asyncio.wait()".

This is also part of learning asyncio and not specific to websockets.

Keep track of the tasks and make sure they terminate or you cancel
them when the connection terminates.


How do I create channels or topics?
-----------------------------------

websockets doesn't have built-in publish / subscribe for these use
cases.

Depending on the scale of your service, a simple in-memory
implementation may do the job or you may need an external publish /
subscribe component.


What does "ConnectionClosedError: code = 1006" mean?
----------------------------------------------------

If you're seeing this traceback in the logs of a server:

   Error in connection handler
   Traceback (most recent call last):
     ...
   asyncio.streams.IncompleteReadError: 0 bytes read on a total of 2 expected bytes

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

   Traceback (most recent call last):
     ...
   websockets.exceptions.ConnectionClosedError: code = 1006 (connection closed abnormally [internal]), no reason

or if a client crashes with this traceback:

   Traceback (most recent call last):
     ...
   ConnectionResetError: [Errno 54] Connection reset by peer

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

   Traceback (most recent call last):
     ...
   websockets.exceptions.ConnectionClosedError: code = 1006 (connection closed abnormally [internal]), no reason

it means that the TCP connection was lost. As a consequence, the
WebSocket connection was closed without receiving a close frame, which
is abnormal.

You can catch and handle "ConnectionClosed" to prevent it from being
logged.

There are several reasons why long-lived connections may be lost:

* End-user devices tend to lose network connectivity often and
  unpredictably because they can move out of wireless network
  coverage, get unplugged from a wired network, enter airplane mode,
  be put to sleep, etc.

* HTTP load balancers or proxies that aren't configured for long-lived
  connections may terminate connections after a short amount of time,
  usually 30 seconds.

If you're facing a reproducible issue, enable debug logs to see when
and how connections are closed.


How can I pass additional arguments to a custom protocol subclass?
------------------------------------------------------------------

You can bind additional arguments to the protocol factory with
"functools.partial()":

   import asyncio
   import functools
   import websockets

   class MyServerProtocol(websockets.WebSocketServerProtocol):
       def __init__(self, extra_argument, *args, **kwargs):
           super().__init__(*args, **kwargs)
           # do something with extra_argument

   create_protocol = functools.partial(MyServerProtocol, extra_argument='spam')
   start_server = websockets.serve(..., create_protocol=create_protocol)

This example was for a server. The same pattern applies on a client.


Why do I get the error: "module 'websockets' has no attribute '...'"?
---------------------------------------------------------------------

Often, this is because you created a script called "websockets.py" in
your current working directory. Then "import websockets" imports this
module instead of the websockets library.


Are there "onopen", "onmessage", "onerror", and "onclose" callbacks?
--------------------------------------------------------------------

No, there aren't.

websockets provides high-level, coroutine-based APIs. Compared to
callbacks, coroutines make it easier to manage control flow in
concurrent code.

If you prefer callback-based APIs, you should use another library.


Can I use "websockets" synchronously, without "async" / "await"?
----------------------------------------------------------------

You can convert every asynchronous call to a synchronous call by
wrapping it in "asyncio.get_event_loop().run_until_complete(...)".

If this turns out to be impractical, you should use another library.


Miscellaneous
=============


How do I set a timeout on "recv()"?
-----------------------------------

Use "wait_for()":

   await asyncio.wait_for(websocket.recv(), timeout=10)

This technique works for most APIs, except for asynchronous context
managers. See issue 574.


How do I keep idle connections open?
------------------------------------

websockets sends pings at 20 seconds intervals to keep the connection
open.

In closes the connection if it doesn't get a pong within 20 seconds.

You can adjust this behavior with "ping_interval" and "ping_timeout".


How do I respond to pings?
--------------------------

websockets takes care of responding to pings with pongs.


Is there a Python 2 version?
----------------------------

No, there isn't.

websockets builds upon asyncio which requires Python 3.
