# Messages Sending and Receiving

## Content

`js-collaboration` facilitates bidirectional client-server communication while enabling server-initiated message broadcasting to all clients within a room. This documentation details the technical implementation of:

* The client sends messages to the server
* The server receives and responds to messages
* Message broadcast

## Basic Sending and Receiving

### Client → Server

The client sends messages to the server using the [connection.send()](/spreadjs/api/v18/collaboration/js-collaboration-client/classes/Connection#send) method. Message supports multiple data types, including strings, plain objects, numbers, and arrays.

```typescript
// Client side
// Send a message to the server
connection.send('hello, world!');
```

The server can receive client messages through the message hook.

```typescript
// Server side
server.on('message', ({ connection, data }) => {
    console.log('Received message from client:', data);
});
```

### Server → Client

The client receives messages from the server using the [connection.on('message')](/spreadjs/api/v18/collaboration/js-collaboration-client/classes/Connection#on) method.

```typescript
//client side
connection.on('message', (data) => {
    console.log('Received message from server:', data);
});
```

The server sends messages to the client using the [connection.send()](/spreadjs/api/v18/collaboration/js-collaboration-client/classes/Connection#send) method.

```typescript
//server side
server.on('connect', ({ connection }) => {
    connection.send('hello, world!');
});
```

## Server Broadcasting

The server can not only send messages to one client but also broadcast messages to all other clients in a room using the [connection.broadcast()](/spreadjs/api/v18/collaboration/js-collaboration/classes/Connection#broadcast) method.

### Broadcast Messages Excluding the Sender

When only the `roomId` parameter is provided to `connection.broadcast()`, the default behavior is to broadcasting messages excluding the sender.
![messages_sending_and_receiving-broadcast1](https://cdn.mescius.io/document-site-files/images/7719ad0a-f083-46d7-aff6-f63e2e187c15/messages_sending_and_receiving-broadcast1.1a1948.png?width=500)

```typescript
// Client side
connection.on('message', (data) => {
    console.log('Received message from server:', data);
});
```

```typescript
// Server side
server.on('connect', ({ connection, roomId }) => {
    // When a client connects, broadcast a message to all clients in the room (excluding the sender)
    connection.broadcast(`${connection.id} join ${roomId}`);
});
```

### Broadcast Messages Including the Sender

To broadcast messages to all room participants including the sender, configure the broadcast method with `includeSelf: true`.
![messages_sending_and_receiving-broadcast2](https://cdn.mescius.io/document-site-files/images/7719ad0a-f083-46d7-aff6-f63e2e187c15/messages_sending_and_receiving-broadcast2.a16051.png?width=500)

```typescript
// Client side
connection.on('message', (data) => {
    console.log('Received message from server:', data);
});// Client side
connection.on('message', (data) => {
    console.log('Received message from server:', data);
});
```

```typescript
// Server side
server.on('connect', ({ connection, roomId }) => {
    // When a client connects, broadcast a message to all clients in the room (including the sender)
    connection.broadcast(`${connection.id} join ${roomId}`, '', true);
});
```

>type=note
> The second parameter of broadcast() is the message type (optional), which is an empty string in this case.

## Message Types

Message types are used to identify the purpose or category of a message, allowing the receiver to determine whether the message is relevant to itself.
For example, in a collaboration scenario, the type could be "my-document" or "my-presence" to distinguish between document update messages and user status messages.

```typescript
// Send a document update
connection.send({ content: 'New paragraph' }, 'my-document');
// Send an online status
connection.send({ userId: 'user1', active: true }, 'my-presence');
// Receive and distinguish messages
connection.on('message', (data, type) => {
    if (type === 'my-document') {
        console.log('Document update:', data);
    } else if (type === 'my-presence') {
        console.log('Status update:', data);
    }
});
```

## Message Order

`js-collaboration` guarantees that messages are delivered in the order they were sent. For example:

```typescript
connection.send('msg1');
connection.send('msg2');
connection.send('msg3');
```

The receiver will always receive the messages in the order: msg1, msg2, msg3.

## Message Delivery

### Delivery Guarantee

`js-collaboration` implements an ​**​At-Most-Once Delivery​**​ mechanism defined as:

* If a message is sent while the connection is disconnected, the system cannot ensure that the recipient has received the message.
* When reconnecting after a disconnection, previously undelivered messages will not be automatically resent.

### Client Behavior

When the connection is disconnected, the client adopts a buffering strategy to try to retain unsent messages.

* **Buffering Unsent Messages**: When the client calls `connection.send()` and the connection is unavailable (e.g., network interruption), the message is not immediately discarded but is buffered locally on the client.
* **Sending After Reconnection**: Once the connection is restored, buffered messages are sent in their original order.

### Server Behavior

The server does not provide a message buffering mechanism. Messages sent during a client disconnection are directly lost.

* **No Buffering of Messages**: When the server sends messages using `connection.send()` or `connection.broadcast()`, if the target client is disconnected, the message is not stored.
* **No Resending**: After a client reconnects, the server does not resend messages that were missed during the disconnection.

## Strategies to Handle Message Loss

Due to the ​At-Most-Once Delivery​​ mechanism, you need to design additional reliability mechanisms based on business requirements. Below is a common strategy:

#### Application-Layer Acknowledgment Mechanism

* **Method**: The sender includes a unique identifier (e.g., message ID) in the message, and the receiver responds with an acknowledgment message.
* **Implementation**: If no acknowledgment is received, the sender can retry.
* **Use Case**: Critical messages (e.g., document changes).

```typescript
// Client sends a message with an ID
connection.send({ id: 'msg123', type: 'update', content: 'xxx' });

// Server acknowledges
server.on('message', ({ connection, data }) => {
    connection.send({ id: data.id, type: 'ack' });
});

// Client checks for acknowledgment
connection.on('message', (data) => {
    if (data.type === 'ack' && data.id === 'msg123') {
        console.log('Message delivered');
    }
});
```