Implementazione della segnalazione di WebrTC utilizzando WebSewet
-
21-12-2019 - |
Domanda
Per collegare peer a peer per la comunicazione utilizzando il WebRTC API
, è necessario implementare la segnalazione.La segnalazione ha bisogno di un canale di comunicazione a due vie per funzionare.WebSockets
sono un canale di comunicazione a due vie.Vorrei usare WebSockets
per implementare la segnalazione, tuttavia, non ho idea di come affrontare questo.Tutto ciò che ho trovato online discute solo i diversi canali a due vie che puoi usare piuttosto che fornire un esempio su come usarli.
Sto usando JavaScript
per il lato client e Java
per il lato server.Quindi, come avrei implementare la segnalazione usando WebSockets
?
Soluzione
Ecco un modo in cui ho capito come farlo. Non ho ancora testato il codice, quindi non sono sicuro se funzioni. Inoltre, sono scettico sul fatto che questo sia efficiente. Se hai una soluzione migliore, vedere un problema nel mio codice o qualsiasi consiglio non esitare a elaborare. L'idea alla base di questo è avere il filtro endpoint del server WebSocket tramite i messaggi e inviarli all'utente appropriato.
- .
-
In primo luogo, sto inviando messaggi ai client utilizzando un ID utente predeterminato. L'endpoint del server WebSocket è solo a conoscenza degli oggetti di sessione che contengono ID di sessione (che non può essere modificato; nessun metodo impostato). Per collegare l'ID sessione e l'ID utente, avrò bisogno di una tabella di database (molto più affidabile che mantenerlo in memoria).
-
Quindi, il primo messaggio inviato all'endpoint del server WebSocket dal client conterrà l'ID dell'utente. Questo sarà mappato al database insieme all'ID della sessione e il client sarà considerato "connesso". Naturalmente, questo succede dopo essere effettivamente collegato al websocket.
-
Ora, una volta "connesso", possiamo inviare (segnalando) i messaggi a un altro utente, purché conosciamo il loro ID utente (che presumo che lo facciamo). L'endpoint del server WebSocket controlla l'ID utente destinatario rispetto al database per trovare il loro ID di sessione. Una volta trovato, il messaggio può essere inviato.
-
Infine, sul lato client, possiamo decifrare il messaggio e inviare la parte posteriore appropriata (utilizzando lo stesso processo sopra).
Quindi, come affermato prima, avremo bisogno di una tabella di database per la sessione dei client e l'ID utente. Dato che sto usando Java per tutto il codice di back-end, utilizzeremo Orm (Mappatura relazionale dell'oggetto) creando una classe di entità per tenere gli attributi. Qualcosa del genere:
@Entity
public class WebSocketUser {
@Id@GeneratedValue
private long id;
private long userId;
private long sessionId;
//constructors, getters and setters
}
.
Ora, possiamo creare la classe Endpoint del server:
@ServerEndpoint("/SignalingServerEndpoint")
public class SignalingServerEndpoint {
//these class variables will be useful for
//access to the database and such
private EntityManagerFactory emf;
private EntityManager em;
private EntityTransaction tx;
private TypedQuery<WebsocketUser> query;
private WebsocketUser wsu;
.
Poiché, non siamo in un EJB, dobbiamo controllare il responsabile dell'entità come in un ambiente gestito dall'applicazione. Aggiungere i metodi OnPen e OnClose al WebSocket:
@OnOpen
public void open(Session session, Endpoint config){
emf = Persistence.createEntityManagerFactory(""); //TODO add persistence unit reference here
em = emf.createEntityManager();
tx = em.getTransaction();
}
@OnClose
public void close(Session session, CloseReason reason){
//if session is closing and information still exists in the database; remove it
if (!wsu.equals(null)){
tx.begin();
em.remove(wsu);
tx.commit();
}
em.close();
emf.close();
}
.
Avanti, nel metodo OnMessage nell'endpoint del server WebSocket, filtrano i messaggi. Ho scelto di inviare messaggi nel formato JSON. Ciò consente di decifrare facilmente le informazioni (ho usato la biblioteca Org.json). Il metodo OnMessage:
@OnMessage
public void message(Session session, String msg){
try {
JSONObject obj = new JSONObject(msg);
if (!obj.has("toUserId")){
//adding user to the database, so they can access their session ID with their user ID
WebsocketUser wsu = new WebsocketUser(obj.getLong("userId"), session.getId());
tx.begin();
em.persist(wsu);
tx.commit();
}else if (obj.has("toUserId")){
//message to be sent to the user with the specified user ID
//get session ID from database
query = em.createQuery("SELECT u FROM WebsocketUser u WHERE u.userId = " + obj.getLong("toUserId"), WebsocketUser.class);
wsu = (WebsocketUser) query.getSingleResult();
Set<Session> sessions = session.getOpenSessions();
for (Iterator<Session> i = sessions.iterator(); i.hasNext();){
Session s = i.next();
if (s.getId().equals(wsu.getSessionId())){
s.getAsyncRemote().sendText(obj.getString("message"));
break;
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
.
Infine, tutto ciò che abbiamo lasciato è il lato client (JavaScript). Creare la variabile del WebSocket:
var signalingSocket = new WebSocket("/SignalingServerEndpoint"); //TODO need the full and correct path to the WebSocket
.
Ora, per il metodo che invierà il messaggio a "Connect" all'endpoint del server WebSocket:
function connect(){
var msg = {
"userId": userId
};
signalingSocket.send(JSON.stringify(msg));
.
E, infine, tutto ciò che abbiamo è il metodo OnMessage sul lato client (che deciferà il messaggio e possibilmente inviare informazioni all'altro client) e tutto il codice di segnalazione effettivo (server di ghiaccio, vincoli, ecc.). Non andrò in tutto il lavoro di segnalazione ma c'è un buon tutorial Qui. Spero che questo aiuti a chiunque altro abbia affrontato un problema simile. Come ho detto, non ho testato il codice quindi non sono positivo se funzionerà. Inoltre, sono molto scettico se questo sarà anche efficiente. Ma è almeno un inizio.