SocketRef

Struct SocketRef 

Source
pub struct SocketRef<A: Adapter = LocalAdapter>(/* private fields */);
Expand description

An Extractor that returns a reference to a Socket.

It is generic over the Adapter type. If you plan to use it with another adapter than the default, make sure to have a handler that is generic over the adapter type.

Implementations§

Source§

impl<A: Adapter> SocketRef<A>

Source

pub fn disconnect(self) -> Result<(), SocketError>

Disconnect the socket from the current namespace,

It will also call the disconnect handler if it is set.

Methods from Deref<Target = Socket<A>>§

Source

pub fn on<H, T>(&self, event: impl Into<Cow<'static, str>>, handler: H)
where H: MessageHandler<A, T>, T: Send + Sync + 'static,

§Registers a MessageHandler for the given event.
  • See the message module doc for more details on message handler.
  • See the extract module doc for more details on available extractors.

It is recommended for code clarity to define your handler as top level function rather than closures.

§Simple example with an async closure and an async fn:
#[derive(Debug, Serialize, Deserialize)]
struct MyData {
    name: String,
    age: u8,
}
async fn handler(socket: SocketRef, Data(data): Data::<MyData>) {
    println!("Received a test message {:?}", data);
    socket.emit("test-test", &MyData { name: "Test".to_string(), age: 8 }).ok(); // Emit a message to the client
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |socket: SocketRef| {
    // Register a handler for the "test" event and extract the data as a `MyData` struct
    // With the Data extractor, the handler is called only if the data can be deserialized as a `MyData` struct
    // If you want to manage errors yourself you can use the TryData extractor
    socket.on("test", async |socket: SocketRef, Data::<MyData>(data)| {
        println!("Received a test message {:?}", data);
        socket.emit("test-test", &MyData { name: "Test".to_string(), age: 8 }).ok(); // Emit a message to the client
    });
    // Do the same thing but with an async function
    socket.on("test_2", handler);
});
§Example with a closure and an fn with an acknowledgement + binary data:
#[derive(Debug, Serialize, Deserialize)]
struct MyData {
    name: String,
    age: u8,
}
async fn handler(socket: SocketRef, Data(data): Data::<MyData>, ack: AckSender) {
    println!("Received a test message {:?}", data);
    tokio::time::sleep(std::time::Duration::from_secs(1)).await;
    ack.send(&data).ok(); // The data received is sent back to the client through the ack
    socket.emit("test-test", &MyData { name: "Test".to_string(), age: 8 }).ok(); // Emit a message to the client
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |socket: SocketRef| {
    // Register an async handler for the "test" event and extract the data as a `MyData` struct
    // Extract the binary payload as a `Vec<Bytes>` with the Bin extractor.
    // It should be the last extractor because it consumes the request
    socket.on("test", async |socket: SocketRef, Data::<MyData>(data), ack: AckSender| {
        println!("Received a test message {:?}", data);
        tokio::time::sleep(std::time::Duration::from_secs(1)).await;
        ack.send(&data).ok(); // The data received is sent back to the client through the ack
        socket.emit("test-test", &MyData { name: "Test".to_string(), age: 8 }).ok(); // Emit a message to the client
    });
    // Do the same thing but with an async function
    socket.on("test_2", handler);
});
Source

pub fn on_fallback<H, T>(&self, handler: H)
where H: MessageHandler<A, T>, T: Send + Sync + 'static,

§Registers a fallback MessageHandler when no other handler is found. You can see this as a 404 handler.

You can register only one fallback handler per socket. If you register multiple handlers, only the last one will be used.

  • See the message module doc for more details on message handler.
  • See the extract module doc for more details on available extractors.

It is recommended for code clarity to define your handler as top level function rather than closures.

§Example:
async fn fallback_handler(socket: SocketRef, Event(event): Event, Data(data): Data::<Value>) {
    println!("Received an {event} event with message {:?}", data);
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |socket: SocketRef| {
    // Register a fallback handler.
    // In our example it will be always called as there is no other handler.
    socket.on_fallback(fallback_handler);
});
Source

pub fn on_disconnect<C, T>(&self, callback: C)
where C: DisconnectHandler<A, T> + Send + Sync + 'static, T: Send + Sync + 'static,

§Register a disconnect handler.

You can register only one disconnect handler per socket. If you register multiple handlers, only the last one will be used.

This implementation is slightly different to the socket.io spec. The difference being that rooms are still available in this handler and only cleaned up AFTER the execution of this handler. Therefore you must not indefinitely stall/hang this handler, for example by entering an endless loop.

It is recommended for code clarity to define your handler as top level function rather than closures.

  • See the disconnect module doc for more details on disconnect handler.
  • See the extract module doc for more details on available extractors.

The callback will be called when the socket is disconnected from the server or the client or when the underlying connection crashes. A DisconnectReason is passed to the callback to indicate the reason for the disconnection.

§Example
let (_, io) = SocketIo::new_svc();
io.ns("/", async |socket: SocketRef| {
    socket.on("test", async |socket: SocketRef| {
        // Close the current socket
        socket.disconnect().ok();
    });
    socket.on_disconnect(async |socket: SocketRef, reason: DisconnectReason| {
        println!("Socket {} on ns {} disconnected, reason: {:?}", socket.id, socket.ns(), reason);
    });
});
Source

pub fn emit<T: ?Sized + Serialize>( &self, event: impl AsRef<str>, data: &T, ) -> Result<(), SendError>

§Emit a message to one or many clients

If you provide tuple-like data (tuples, arrays), it will be considered as multiple arguments. Therefore, if you want to send an array as the first argument of the payload, you need to wrap it in an array or a tuple. A Vec will always be considered a single argument.

§Emitting binary data

To emit binary data, you must use a data type that implements Serialize as binary data. Currently, if you use Vec<u8>, it will be considered a sequence of numbers rather than binary data. To handle this, you can either use a special type like Bytes or the serde_bytes crate. If you want to emit generic data that may contain binary, use rmpv::Value instead of serde_json::Value, as binary data will otherwise be serialized as a sequence of numbers.

§Errors
§Single-socket example
async fn handler(socket: SocketRef, Data(data): Data::<Value>) {
    // Emit a test message to the client
    socket.emit("test", &data).ok();
    // Emit a test message with multiple arguments to the client
    socket.emit("test", &("world", "hello", 1)).ok();
    // Emit a test message with an array as the first argument
    let arr = [1, 2, 3, 4];
    socket.emit("test", &[arr]).ok();
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |socket: SocketRef| socket.on("test", handler));
§Single-socket binary example with the bytes crate
async fn handler(socket: SocketRef, Data(data): Data::<(String, Bytes, Bytes)>) {
    // Emit a test message to the client
    socket.emit("test", &data).ok();
    // Emit a test message with multiple arguments to the client
    socket.emit("test", &("world", "hello", Bytes::from_static(&[1, 2, 3, 4]))).ok();
    // Emit a test message with an array as the first argument
    let arr = [1, 2, 3, 4];
    socket.emit("test", &[arr]).ok();
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |socket: SocketRef| socket.on("test", handler));
§Broadcast example

Here the emit method will return a Future that must be awaited because socket.io may communicate with remote instances if you use horizontal scaling through remote adapters.

async fn handler(socket: SocketRef, Data(data): Data::<(String, Bytes, Bytes)>) {
    // Emit a test message in the room1 and room3 rooms, except for room2, with the received binary payload
    socket.to("room1").to("room3").except("room2").emit("test", &data).await;

    // Emit a test message with multiple arguments to the client
    socket.to("room1").emit("test", &("world", "hello", 1)).await;

    // Emit a test message with an array as the first argument
    let arr = [1, 2, 3, 4];
    socket.to("room2").emit("test", &[arr]).await;
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |s: SocketRef| s.on("test", handler));
Source

pub fn emit_with_ack<T: ?Sized + Serialize, V>( &self, event: impl AsRef<str>, data: &T, ) -> Result<AckStream<V>, SendError>

§Emit a message to one or many clients and wait for one or more acknowledgments.

See emit() for more details on emitting messages.

The acknowledgment has a timeout specified in the config (5 seconds by default) (see SocketIoBuilder::ack_timeout) or can be set with the timeout() operator.

To receive acknowledgments, an AckStream is returned. It can be used in two ways:

  • As a Stream: This will yield all the acknowledgment responses, along with the corresponding socket ID, received from the client. This is useful when broadcasting to multiple sockets and expecting more than one acknowledgment. To get the socket from this ID, use io::get_socket().
  • As a Future: This will yield the first acknowledgment response received from the client, useful when expecting only one acknowledgment.
§Errors

If packet encoding fails, an ParserError is immediately returned.

If the socket is full or if it is closed before receiving the acknowledgment, a SendError::Socket will be immediately returned, and the value to send will be given back.

If the client does not respond before the timeout, the AckStream will yield an AckError::Timeout. If the data sent by the client is not deserializable as V, an AckError::Decode will be yielded.

§Single-socket example
async fn handler(socket: SocketRef, Data(data): Data::<Value>) {
    // Emit a test message and wait for an acknowledgment with the timeout specified in the global config
    match socket.emit_with_ack::<_, Value>("test", &data).unwrap().await {
        Ok(ack) => println!("Ack received {:?}", ack),
        Err(err) => println!("Ack error {:?}", err),
    }
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |socket: SocketRef| socket.on("test", handler));
§Single-socket example with custom acknowledgment timeout
async fn handler(socket: SocketRef, Data(data): Data::<Value>) {
    // Emit a test message and wait for an acknowledgment with the timeout specified here
    match socket.timeout(Duration::from_millis(2)).emit_with_ack::<_, Value>("test", &data).unwrap().await {
        Ok(ack) => println!("Ack received {:?}", ack),
        Err(err) => println!("Ack error {:?}", err),
    }
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |socket: SocketRef| socket.on("test", handler));
§Broadcast example

Here the emit method will return a Future that must be awaited because socket.io may communicate with remote instances if you use horizontal scaling through remote adapters.

async fn handler(socket: SocketRef, Data(data): Data::<Value>) {
    // Emit a test message in the room1 and room3 rooms,
    // except for room2, with the binary payload received
    let ack_stream = socket.to("room1")
        .to("room3")
        .except("room2")
        .emit_with_ack::<_, String>("message-back", &data)
        .await
        .unwrap();
    ack_stream.for_each(async |(id, ack)| {
        match ack {
            Ok(ack) => println!("Ack received, socket {} {:?}", id, ack),
            Err(err) => println!("Ack error, socket {} {:?}", id, err),
        }
    }).await;
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |s: SocketRef| s.on("test", handler));
Source

pub fn join(&self, rooms: impl RoomParam)

§Add the current socket to the specified room(s).
§Example
async fn handler(socket: SocketRef) {
    // Add all sockets that are in room1 and room3 to room4 and room5
    socket.join(["room4", "room5"]);
    // We should retrieve all the local sockets that are in room3 and room5
    let sockets = socket.within("room4").within("room5").sockets();
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |s: SocketRef| s.on("test", handler));
Source

pub fn leave(&self, rooms: impl RoomParam)

§Remove the current socket from the specified room(s).
§Example
async fn handler(socket: SocketRef) {
    // Remove all sockets that are in room1 and room3 from room4 and room5
    socket.within("room1").within("room3").leave(["room4", "room5"]);
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |s: SocketRef| s.on("test", handler));
Source

pub fn leave_all(&self)

§Remove the current socket from all its rooms.
Source

pub fn rooms(&self) -> Vec<Room>

§Get all room names this socket is connected to.
§Example
async fn handler(socket: SocketRef) {
    println!("Socket connected to the / namespace with id: {}", socket.id);
    socket.join(["room1", "room2"]);
    let rooms = socket.rooms();
    println!("All rooms in the / namespace: {:?}", rooms);
}

let (_, io) = SocketIo::new_svc();
io.ns("/", handler);
Source

pub fn connected(&self) -> bool

§Return true if the socket is connected to the namespace.

A socket is considered connected when it has been successfully handshaked with the server and that all connect middlewares have been executed.

Source

pub fn to(&self, rooms: impl RoomParam) -> BroadcastOperators<A>

§Select all the sockets in the given rooms except for the current socket.

When called from a socket, if you want to also include it, use the within() operator.

However, when called from the io (global context) level, there will be no difference.

§Example
async fn handler(socket: SocketRef, io: SocketIo, Data(data): Data::<Value>) {
    // Emit a message to all sockets in room1, room2, room3, and room4, except the current socket
    socket
        .to("room1")
        .to(["room2", "room3"])
        .emit("test", &data)
        .await;

    // Emit a message to all sockets in room1, room2, room3, and room4, including the current socket
    io
        .to("room1")
        .to(["room2", "room3"])
        .emit("test", &data)
        .await;
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |s: SocketRef| s.on("test", handler));
Source

pub fn within(&self, rooms: impl RoomParam) -> BroadcastOperators<A>

§Select all the sockets in the given rooms (current one included).

This includes the current socket, in contrast to the to() operator.

However, when called from the io (global context) level, there will be no difference.

§Example
async fn handler(socket: SocketRef, Data(data): Data::<Value>) {
    let other_rooms = "room4".to_string();
    // Emit a message to all sockets in room1, room2, room3, and room4, including the current socket
    socket
        .within("room1")
        .within(["room2", "room3"])
        .within(vec![other_rooms])
        .emit("test", &data)
        .await;
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |s: SocketRef| s.on("test", handler));
Source

pub fn except(&self, rooms: impl RoomParam) -> BroadcastOperators<A>

§Filter out all sockets selected with the previous operators that are in the specified rooms.
§Example
async fn handler(socket: SocketRef, Data(data): Data::<Value>) {
    // This message will be broadcast to all sockets in the namespace,
    // except for those in room1 and the current socket
    socket.broadcast().except("room1").emit("test", &data).await;
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |socket: SocketRef| {
    socket.on("register1", async |s: SocketRef| s.join("room1"));
    socket.on("register2", async |s: SocketRef| s.join("room2"));
    socket.on("test", handler);
});
Source

pub fn local(&self) -> BroadcastOperators<A>

§Broadcast to all sockets only connected to this node.

When using the default in-memory adapter, this operator is a no-op.

§Example
async fn handler(socket: SocketRef, Data(data): Data::<Value>) {
    // This message will be broadcast to all sockets in this
    // namespace that are connected to this node
    socket.local().emit("test", &data).await;
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |s: SocketRef| s.on("test", handler));
Source

pub fn timeout(&self, timeout: Duration) -> ConfOperators<'_, A>

§Set a custom timeout when sending a message with an acknowledgement.
§Example
async fn handler(socket: SocketRef, Data(data): Data::<Value>) {
    // Emit a test message in the room1 and room3 rooms, except for the room2
    // room with the binary payload received, and wait for 5 seconds for an acknowledgement
    socket.to("room1")
          .to("room3")
          .except("room2")
          .timeout(Duration::from_secs(5))
          .emit_with_ack::<_, Value>("message-back", &data)
          .await
          .unwrap()
          .for_each(async |(id, ack)| {
            match ack {
                Ok(ack) => println!("Ack received from socket {}: {:?}", id, ack),
                Err(err) => println!("Ack error from socket {}: {:?}", id, err),
            }
          }).await;
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |s: SocketRef| s.on("test", handler));
Source

pub fn broadcast(&self) -> BroadcastOperators<A>

§Broadcast to all sockets without any filtering (except the current socket).

If you want to include the current socket use the broadcast operators from the io global context.

§Example
async fn handler(io: SocketIo, socket: SocketRef, Data(data): Data::<Value>) {
    // This message will be broadcast to all sockets in this namespace except this one.
    socket.broadcast().emit("test", &data).await;
    // This message will be broadcast to all sockets in this namespace, including this one.
    io.emit("test", &data).await;
}

let (_, io) = SocketIo::new_svc();
io.ns("/", async |s: SocketRef| s.on("test", handler));
Source

pub fn disconnect(self: Arc<Self>) -> Result<(), SocketError>

§Disconnect the socket from the current namespace,

It will also call the disconnect handler if it is set with a DisconnectReason::ServerNSDisconnect.

Source

pub fn req_parts(&self) -> &Parts

§Get the request info made by the client to connect.

It might be used to retrieve the http::Extensions

Source

pub fn transport_type(&self) -> TransportType

§Get the TransportType used by the client to connect with this Socket.

It can also be accessed as an extractor

§Example

let (_, io) = SocketIo::new_svc();
io.ns("/", async |socket: SocketRef, transport: TransportType| {
    assert_eq!(socket.transport_type(), transport);
});
Source

pub fn protocol(&self) -> ProtocolVersion

Get the socket.io ProtocolVersion used by the client to connect with this Socket.

It can also be accessed as an extractor:

§Example

let (_, io) = SocketIo::new_svc();
io.ns("/", async |socket: SocketRef, v: ProtocolVersion| {
    assert_eq!(socket.protocol(), v);
});
Source

pub fn ns(&self) -> &str

§Get the socket namespace path.

Trait Implementations§

Source§

impl<A: Adapter> Clone for SocketRef<A>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<A: Adapter> Debug for SocketRef<A>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<A: Adapter> Deref for SocketRef<A>

Source§

type Target = Socket<A>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<A: Adapter> From<Arc<Socket<A>>> for SocketRef<A>

Source§

fn from(socket: Arc<Socket<A>>) -> Self

Converts to this type from the input type.
Source§

impl<A: Adapter> FromConnectParts<A> for SocketRef<A>

Source§

type Error = Infallible

The error type returned by the extractor
Source§

fn from_connect_parts( s: &Arc<Socket<A>>, _: &Option<Value>, ) -> Result<Self, Infallible>

Extract the arguments from the connect event. If it fails, the handler is not called
Source§

impl<A: Adapter> FromDisconnectParts<A> for SocketRef<A>

Source§

type Error = Infallible

The error type returned by the extractor
Source§

fn from_disconnect_parts( s: &Arc<Socket<A>>, _: DisconnectReason, ) -> Result<Self, Infallible>

Extract the arguments from the disconnect event. If it fails, the handler is not called
Source§

impl<A: Adapter> FromMessageParts<A> for SocketRef<A>

Source§

type Error = Infallible

The error type returned by the extractor
Source§

fn from_message_parts( s: &Arc<Socket<A>>, _: &mut Value, _: &Option<i64>, ) -> Result<Self, Infallible>

Extract the arguments from the message event. If it fails, the handler is not called.
Source§

impl<A: Adapter> PartialEq for SocketRef<A>

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto Trait Implementations§

§

impl<A> Freeze for SocketRef<A>

§

impl<A = LocalAdapter> !RefUnwindSafe for SocketRef<A>

§

impl<A> Send for SocketRef<A>

§

impl<A> Sync for SocketRef<A>

§

impl<A> Unpin for SocketRef<A>

§

impl<A = LocalAdapter> !UnwindSafe for SocketRef<A>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more