ezsockets icon indicating copy to clipboard operation
ezsockets copied to clipboard

Ping/Pong frames

Open rlgrpe opened this issue 10 months ago • 2 comments

#114 #115 @gbaranski

I understand that I can send pings intermittently using this library. But, for example, in the case of a binance, I need to respond to pings from the server with a pong from the client.

you say "Also, the client will automatically respond to any ping with a pong" -

impl<M, S> StreamActor<M, S>
where
    M: Into<RawMessage>,
    S: StreamExt<Item = Result<M, WSError>> + Unpin,
{
    async fn run(mut self) {
        while let Some(result) = self.stream.next().await {
            let result = result.map(M::into);
            tracing::trace!("received message: {:?}", result);
            *self.last_alive.lock().await = Instant::now();

            let mut closing = false;
            let message = match result {
                Ok(message) => Ok(match message {
                    RawMessage::Text(text) => Message::Text(text),
                    RawMessage::Binary(bytes) => Message::Binary(bytes),
                    RawMessage::Ping(_bytes) => continue,
                    RawMessage::Pong(bytes) => {
                        if let Ok(bytes) = bytes.try_into() {
                            let bytes: [u8; 16] = bytes;
                            let timestamp = u128::from_be_bytes(bytes);
                            let timestamp = Duration::from_millis(timestamp as u64); // TODO: handle overflow
                            let latency = SystemTime::now()
                                .duration_since(UNIX_EPOCH + timestamp)
                                .unwrap_or_default();
                            // TODO: handle time zone
                            tracing::trace!("latency: {}ms", latency.as_millis());
                        }

                        continue;
                    }
                    RawMessage::Close(frame) => {
                        closing = true;
                        Message::Close(frame)
                    }
                }),
                Err(err) => Err(err), // maybe early return here?

As I understand, this part of the code is responsible for the example and converting a message from tokio_tungstenite::Message to Message inside the library.

Here Ping frame is simply ignored, so I can't do the necessary realisation.

This is confirmed by a practical example, I can't get a Ping frame either through Binary or Call and after a short time I get a connection failure

Image

In my realisation there is no such problem, the connection is not dropping

rlgrpe avatar Feb 02 '25 10:02 rlgrpe

In case you don't want to burden the user with a ping response, then my realsituation is not very suitable. You just need to do automatic processing RawMessage::Ping(bytes) => // send RawMessage::Pong(bytes).

rlgrpe avatar Feb 02 '25 10:02 rlgrpe

Here Ping frame is simply ignored, so I can't do the necessary realisation.

Pings are automatically responded-to by the backend implementation tokio_tungstenite for native clients. If you have a web client then Pings are completely ignored by the browser backend and there's nothing we can do about it (there is no API to get ping data in the browser, nor can you send pings or pongs).

UkoeHB avatar Feb 02 '25 20:02 UkoeHB

I consider this as resolved. Feel free to open in the future if you encounter the same issue.

gbaranski avatar Nov 05 '25 12:11 gbaranski