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: SidThe socket id
extensions: Extensionsextensions 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>
impl<A: Adapter> Socket<A>
sourcepub fn on<H, T>(&self, event: impl Into<Cow<'static, str>>, handler: H)
pub fn on<H, T>(&self, event: impl Into<Cow<'static, str>>, handler: H)
Registers a MessageHandler for the given event.
- See the
messagemodule doc for more details on message handler. - See the
extractmodule 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
});
});sourcepub fn on_disconnect<C, T>(&self, callback: C)
pub fn on_disconnect<C, T>(&self, callback: C)
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
disconnectmodule doc for more details on disconnect handler. - See the
extractmodule 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);
});
});sourcepub fn emit(
&self,
event: impl Into<Cow<'static, str>>,
data: impl Serialize
) -> Result<(), SendError>
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::Serializemay 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. SeeSocketIoBuilder::max_buffer_sizeoption 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();
});
});sourcepub fn emit_with_ack<V>(
&self,
event: impl Into<Cow<'static, str>>,
data: impl Serialize
) -> Result<AckStream<V>, Error>
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 theAckResponsewith 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, useio::get_socket(). - As a
Future: It will yield the firstAckResponsereceived 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),
}
});
});sourcepub fn join(&self, rooms: impl RoomParam) -> Result<(), A::Error>
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
sourcepub fn leave(&self, rooms: impl RoomParam) -> Result<(), A::Error>
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
sourcepub fn leave_all(&self) -> Result<(), A::Error>
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
sourcepub fn rooms(&self) -> Result<Vec<Room>, A::Error>
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
sourcepub fn to(&self, rooms: impl RoomParam) -> Operators<A>
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);
});
});sourcepub fn within(&self, rooms: impl RoomParam) -> Operators<A>
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);
});
});sourcepub fn except(&self, rooms: impl RoomParam) -> Operators<A>
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);
});
});sourcepub fn local(&self) -> Operators<A>
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);
});
});sourcepub fn timeout(&self, timeout: Duration) -> Operators<A>
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;
});
});sourcepub fn bin(&self, binary: Vec<Vec<u8>>) -> Operators<A>
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);
});
});sourcepub fn broadcast(&self) -> Operators<A>
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);
});
});sourcepub fn disconnect(self: Arc<Self>) -> Result<(), DisconnectError>
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.
sourcepub fn req_parts(&self) -> &Parts
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]
sourcepub fn transport_type(&self) -> TransportType
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);
});sourcepub fn protocol(&self) -> ProtocolVersion
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);
});