Struct socketioxide::socket::Socket

source ·
pub struct Socket<A: Adapter = LocalAdapter> {
    pub id: Sid,
    pub extensions: Extensions,
    /* private fields */
}
Expand description

A Socket represents a client connected to a namespace. It is used to send and receive messages from the client, join and leave rooms, etc. The socket struct itself should not be used directly, but through a SocketRef.

Fields§

§id: Sid

The socket id

§extensions: Extensions
Available on crate feature extensions only.

A type map of protocol extensions. It can be used to share data through the lifetime of the socket. Because it uses a DashMap internally, it is thread safe but be careful about deadlocks!

Note: This is note the same data than the extensions field on the http::Request::extensions() struct.

Implementations§

source§

impl<A: Adapter> 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.
Simple example with a sync closure:
#[derive(Debug, Serialize, Deserialize)]
struct MyData {
    name: String,
    age: u8,
}

let (_, io) = SocketIo::new_svc();
io.ns("/", |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", |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
    });
});
Example with a closure and an acknowledgement + binary data:
#[derive(Debug, Serialize, Deserialize)]
struct MyData {
    name: String,
    age: u8,
}

let (_, io) = SocketIo::new_svc();
io.ns("/", |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<Vec<u8>>` with the Bin extractor.
    // It should be the last extractor because it consumes the request
    socket.on("test", |socket: SocketRef, Data::<MyData>(data), ack: AckSender, Bin(bin)| async move {
        println!("Received a test message {:?}", data);
        tokio::time::sleep(std::time::Duration::from_secs(1)).await;
        ack.bin(bin).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
    });
});
source

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

Registers a disconnect handler.

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

  • 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("/", |socket: SocketRef| {
    socket.on("test", |socket: SocketRef| async move {
        // Close the current socket
        socket.disconnect().ok();
    });
    socket.on_disconnect(|socket: SocketRef, reason: DisconnectReason| async move {
        println!("Socket {} on ns {} disconnected, reason: {:?}", socket.id, socket.ns(), reason);
    });
});
source

pub fn emit( &self, event: impl Into<Cow<'static, str>>, data: impl Serialize ) -> Result<(), SendError>

Emits a message to the client

If you provide array-like data (tuple, vec, 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.

Errors
  • When encoding the data into JSON a SendError::Serialize may be returned.
  • If the underlying engine.io connection is closed a [SendError::Socket(SocketError::Closed)] will be returned.
  • If the packet buffer is full, a [SendError::Socket(SocketError::InternalChannelFull)] will be returned. See SocketIoBuilder::max_buffer_size option for more infos on internal buffer config
Example
let (_, io) = SocketIo::new_svc();
io.ns("/", |socket: SocketRef| {
    socket.on("test", |socket: SocketRef, Data::<Value>(data)| async move {
        // 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();
    });
});
source

pub fn emit_with_ack<V>( &self, event: impl Into<Cow<'static, str>>, data: impl Serialize ) -> Result<AckStream<V>, Error>

Emits a message to the client and wait for acknowledgement.

The acknowledgement has a timeout specified in the config (5s by default) (see SocketIoBuilder::ack_timeout) or with the timeout() operator.

To get acknowledgements, an AckStream is returned. It can be used in two ways:

  • As a Stream: It will yield all the AckResponse with their corresponding socket id received from the client. It can useful when broadcasting to multiple sockets and therefore expecting more than one acknowledgement. If you want to get the socket from this id, use io::get_socket().
  • As a Future: It will yield the first AckResponse received from the client. Useful when expecting only one acknowledgement.

If the packet encoding failed a serde_json::Error is immediately returned.

If the socket is full or if it has been closed before receiving the acknowledgement, an AckError::Socket will be yielded.

If the client didn’t 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::Serde will be yielded.

Basic example
let (_, io) = SocketIo::new_svc();
io.ns("/", |socket: SocketRef| {
    socket.on("test", |socket: SocketRef, Data::<Value>(data)| async move {
        // Emit a test message and wait for an acknowledgement with the timeout specified in the config
        match socket.emit_with_ack::<Value>("test", data).unwrap().await {
            Ok(ack) => println!("Ack received {:?}", ack),
            Err(err) => println!("Ack error {:?}", err),
        }
   });
});
source

pub fn join(&self, rooms: impl RoomParam) -> Result<(), A::Error>

Joins the given rooms.

If the room does not exist, it will be created.

Errors

When using a distributed adapter, it can return an Adapter::Error which is mostly related to network errors. For the default LocalAdapter it is always an Infallible error

source

pub fn leave(&self, rooms: impl RoomParam) -> Result<(), A::Error>

Leaves the given rooms.

If the room does not exist, it will do nothing

Errors

When using a distributed adapter, it can return an Adapter::Error which is mostly related to network errors. For the default LocalAdapter it is always an Infallible error

source

pub fn leave_all(&self) -> Result<(), A::Error>

Leaves all rooms where the socket is connected.

Errors

When using a distributed adapter, it can return an Adapter::Error which is mostly related to network errors. For the default LocalAdapter it is always an Infallible error

source

pub fn rooms(&self) -> Result<Vec<Room>, A::Error>

Gets all rooms where the socket is connected.

Errors

When using a distributed adapter, it can return an Adapter::Error which is mostly related to network errors. For the default LocalAdapter it is always an Infallible error

source

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

Selects all clients in the given rooms except the current socket.

If you want to include the current socket, use the within() operator.

Example
let (_, io) = SocketIo::new_svc();
io.ns("/", |socket: SocketRef| {
    socket.on("test", |socket: SocketRef, Data::<Value>(data)| async move {
        let other_rooms = "room4".to_string();
        // In room1, room2, room3 and room4 except the current
        socket
            .to("room1")
            .to(["room2", "room3"])
            .to(vec![other_rooms])
            .emit("test", data);
    });
});
source

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

Selects all clients in the given rooms.

It does include the current socket contrary to the to() operator.

Example
let (_, io) = SocketIo::new_svc();
io.ns("/", |socket: SocketRef| {
    socket.on("test", |socket: SocketRef, Data::<Value>(data)| async move {
        let other_rooms = "room4".to_string();
        // In room1, room2, room3 and room4 including the current socket
        socket
            .within("room1")
            .within(["room2", "room3"])
            .within(vec![other_rooms])
            .emit("test", data);
    });
});
source

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

Filters out all clients selected with the previous operators which are in the given rooms.

Example
let (_, io) = SocketIo::new_svc();
io.ns("/", |socket: SocketRef| {
    socket.on("register1", |socket: SocketRef, Data::<Value>(data)| async move {
        socket.join("room1");
    });
    socket.on("register2", |socket: SocketRef, Data::<Value>(data)| async move {
        socket.join("room2");
    });
    socket.on("test", |socket: SocketRef, Data::<Value>(data)| async move {
        // This message will be broadcast to all clients in the Namespace
        // except for ones in room1 and the current socket
        socket.broadcast().except("room1").emit("test", data);
    });
});
source

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

Broadcasts to all clients only connected on this node (when using multiple nodes). When using the default in-memory LocalAdapter, this operator is a no-op.

Example
let (_, io) = SocketIo::new_svc();
io.ns("/", |socket: SocketRef| {
    socket.on("test", |socket: SocketRef, Data::<Value>(data)| async move {
        // This message will be broadcast to all clients in this namespace and connected on this node
        socket.local().emit("test", data);
    });
});
source

pub fn timeout(&self, timeout: Duration) -> Operators<A>

Sets a custom timeout when sending a message with an acknowledgement.

See SocketIoBuilder::ack_timeout for the default timeout.

See emit_with_ack() for more details on acknowledgements.

Example
let (_, io) = SocketIo::new_svc();
io.ns("/", |socket: SocketRef| {
   socket.on("test", |socket: SocketRef, Data::<Value>(data), Bin(bin)| async move {
      // Emit a test message in the room1 and room3 rooms, except for the room2 room with the binary payload received, wait for 5 seconds for an acknowledgement
      socket.to("room1")
            .to("room3")
            .except("room2")
            .bin(bin)
            .timeout(Duration::from_secs(5))
            .emit_with_ack::<Value>("message-back", data)
            .unwrap()
            .for_each(|(sid, ack)| async move {
               match ack {
                   Ok(ack) => println!("Ack received, socket {} {:?}", sid, ack),
                   Err(err) => println!("Ack error, socket {} {:?}", sid, err),
               }
            }).await;
   });
});
source

pub fn bin(&self, binary: Vec<Vec<u8>>) -> Operators<A>

Adds a binary payload to the message.

Example
let (_, io) = SocketIo::new_svc();
io.ns("/", |socket: SocketRef| {
    socket.on("test", |socket: SocketRef, Data::<Value>(data), Bin(bin)| async move {
        // This will send the binary payload received to all clients in this namespace with the test message
        socket.bin(bin).emit("test", data);
    });
});
source

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

Broadcasts to all clients without any filtering (except the current socket).

Example
let (_, io) = SocketIo::new_svc();
io.ns("/", |socket: SocketRef| {
    socket.on("test", |socket: SocketRef, Data::<Value>(data)| async move {
        // This message will be broadcast to all clients in this namespace
        socket.broadcast().emit("test", data);
    });
});
source

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

Disconnects the socket from the current namespace,

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

source

pub fn ns(&self) -> &str

Gets the current namespace path.

source

pub fn req_parts(&self) -> &Parts

Gets the request info made by the client to connect

It might be used to retrieve the [http::request::Extensions]

source

pub fn transport_type(&self) -> TransportType

Gets the TransportType used by the client to connect with this Socket

It can also be accessed as an extractor:


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

pub fn protocol(&self) -> ProtocolVersion

Gets 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("/", |socket: SocketRef, v: ProtocolVersion| {
    assert_eq!(socket.protocol(), v);
});

Trait Implementations§

source§

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

source§

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

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

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

source§

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

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

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

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

Auto Trait Implementations§

§

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

§

impl<A> Send for Socket<A>

§

impl<A> Sync for Socket<A>

§

impl<A> Unpin for Socket<A>

§

impl<A = LocalAdapter> !UnwindSafe for Socket<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> 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<T> Same for T

§

type Output = T

Should always be Self
source§

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

§

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>,

§

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.
§

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

§

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