I want to realize a client/server architecture (web browser clients <-> backend nodejs server), using a communication protocol to exchange 1-to-1 binary/voice messages between web clients and the backend server (a "voice assistant/bot").
I chose socketio as websocket protocol. This is the basic message exchange flow:
clients requests to the server (pull mode)
- Each js client, running on a web browser, send an audio/voice message to the nodejs server.
- The server does some elaboration on the inbound message and reply the sender client with an outbound voice message ONLY to the specific client.
server notification to a client (push mode)
- under some server-side events, the server send an unsolicited message a certain client
+----------------+ +------------------+
| | | |
+--+ | | | |
| | web browser | | | |
user 1 | +--------------> https | | |
| <--------------+ web server | | |
+--+ | for | | |
| static assets | | |
+--+ | | | |
| | web browser | | | cobot <--------+
user 2 | +--------------> +---> dialog +------+ |
| <--------------+ +---+ manager | | |
+--+ | socketio | | server | | |
| server | | logic | | |
| for audio / | | | | |
+--+ | video | | | | |
| | web browser | messages | | | | |
user N | +--------------> | | | | |
| <--------------+ | | | | |
+--+ | | | | | |
| | | | | |
+----------------+ +------------------+ | |
| |
Maybe one could call "unicast" this client-server communication. Server side, that's the usual behavior of a web server that receives a request from a certain client and serve the request replying to this client.
I'm confused about out to use socketio API to realize the scenario described. If I well understood socketio architecture:
- the server can reply a message to a connected client with a 1-to-1 message (see also the emit-cheatsheet):
// sending to sender-client only
socket.emit('messageType', 'message payload');
- But how can each client sends a message (the voice message request) just to the server node (avoiding the broadcast to all clients, typical of many chat-app socketio examples)?
Is
room
socketio concept a solution? I think about assigning a room to each client (a user), allowing users to connect from different devices with auser_id
(room_id
=user_id
). In this scenario, I guess each client have to join his "dedicated" room. Right?
UPDATE
reading interesting question /answers: socket.io private message and How synchronise socketIO connection ID's on client and server?, I sketched this pseudocode, following the idea to associate a room to each private bidirectional client/server channel:
The client:
//
// client side
//
const user_id = 'username'
const audioBlob = ... // audioChunks blob from MediaRecorder
// join the room with his user_id as name
socket.join(user_id)
// new user (= room) registration
// notify the server about this new connection
socket.emit('user_id', user_id)
...
// client send a message (request) to the server
// on room with name user_id, excluding sender as recipients
socket.broadcast.to(user_id).emit('audioMessage', audioBlob)
...
// client receive a message
// audio message received from server (the answer to the request)
socket.on('audioMessage', audioBlob =>
playAudio(audioBlob) )
The server:
//
// server side
//
io.on('connection', socket => {
// pair/associate the socket with a room name
socket.on('user_id', user_id => {
socket.join(user_id)
// store somewhere association: {socket.id, user_id}
storeOnDB(socket, user_id)
})
// server receives a message from a client (pull request)
// the server elaborates the message
// and sends back to the user an answer
// (all clients in 'uid' room except sender, the server itself)
socket.on('audioMessage', msg => {
// retrieve the room name to which socket belongs
const user_id = getFromDB(socket)
socket.broadcast.to(user_id).emit('audioMessage', answerTo(msg))
})
}
...
// server sends an unsolicited/push message to a user
// (client socket on a room)
io.to('some uid').emit('some notification', data)
Does the pseudo-code make sense/it's correct?