rbeeli / websocketclient-cpp

A transport-agnostic, high-performance, header-only C++23 WebSocket client library with minimal dependencies.
MIT License
1 stars 1 forks source link

Automatic handling of server PING frames #3

Closed MeanSquaredError closed 2 months ago

MeanSquaredError commented 2 months ago

Hi,

From the synchronous example it seems that the handling of ping/pong messages is manual. It probably makes sense to add some kind of support for the automatic handling of PING/PONG messages, pretty much like Boost Beast handles them. If a boost/beast ws client tries to read a frame from the server and a ping message is found, then the corresponding pong message is sent automatically and not returned to the caller.

It makes sense in most cases to handle pings automatically because this is what the user will do anyway.

This support for the automatic ping/pong handling can be configurable through a boolean flag, so if the user wishes he could handle these messages manually.

rbeeli commented 2 months ago

Hi,

As you can see from the README.md, this is by design and considered a feature:

No hidden networking control flow
- User decides when and what to write as response to ping/close frames

Handling a ping frame sequentially is effectively 2 lines of code, see ex_echo_sync.cpp.

This also has to do with the fact that the client is not thread-aware, and the handing of pong frames introduces another write operation to the server, which might be unwanted to deal with at that point of the read operation. For example, for latency sensitive applications, the pong frame would need to be handled in parallel to the read thread. Implementing this would require thread-awareness within the client and additional synchronization primitives, which I want to avoid. As you can see, there is no unique way to implement this.

This gets even more complicated in the async client based on C++20 coroutines. It would require the async client implementation to know about the executor in order to spawn concurrent write calls on the write strand (e.g. in ASIO), and this is to my knowledge not possible to cleanly abstract away.

To avoid this complexity and having do deal with threading and scheduling in an opinionated way, my solution is simply to return the PingFrame to the user and let the user decide when and how to handle it. Not obvious at first sight, but this reduces the complexity of the client implementation a lot.

rbeeli commented 2 months ago

To summarize, automatically handling Ping frames is not something I plan to add due to the reasons mentioned above.

MeanSquaredError commented 2 months ago

OK, thank you for the clarification.