Il primo server che impareremo ad implementare sarà un WebSocket server in C#. Per farlo, utilizzeremo una libreria molto semplice da utilizzare, ma al tempo stesso completa e abbastanza diffusa: Fleck. Fleck è open source, ed il codice sorgente può essere scaricato direttamente da GitHub. Se la vostra IDE di riferimento è una versione di Visual Studio compatibile con NuGet, potete utilizzare quest'ultimo per installare Fleck.
L'utilizzo di questa libreria è estremamente semplice, e ricorda molto le API disponibili su JavaScript. Tale similarità si può notare sin da subito, osservando il codice che segue:
var socket = new WebSocketServer("ws://127.0.0.1:8081/");
socket.Start(conn =>
{
conn.OnOpen = () =>
{
// Metodo eseguito all'apertura della connessione
};
conn.OnMessage = message =>
{
// Metodo eseguito alla ricezione di un messaggio
// La stringa 'message' rappresenta il messaggio
Console.WriteLine(message); // Stampa il messaggio
};
conn.OnClose = () =>
{
// Metodo eseguito alla chiusura della connessione
};
});
Nell'esempio, abbiamo dichiarato un WebSocketServer
che ascolta sulla porta 8081 locale, senza sfruttare alcuna funzionalità di cifratura (dal momento che abbiamo utilizzato il prefisso ws://
). Vedremo più avanti in questo articolo come realizzare una connessione sicura.
In maniera simile a quanto visto con JavaScript, anche qui abbiamo la possibilità di eseguire del codice in corrispondenza dell'apertura (conn.OnOpen
) e chiusura (conn.OnClose
) della connessione, nonchè alla ricezione di un messaggio (conn.OnMessage
), utilizzando la stringa message
per leggerne il contenuto. I metodi appena citati appartengono all'oggetto conn
, istanza della classe IWebSocketConnection
.
È altresì possibile inviare messaggi dal server al client, sfruttando il metodo Send
della classe IWebSocketConnection
, che accetta come parametro una stringa rappresentante il messaggio. Per farlo, abbiamo bisogno di memorizzare l'oggetto conn
visto in precedenza, facendo sì che esso sia accessibile anche fuori dalla dichiarazione del WebSocketServer
. Modifichiamo quindi il codice precedente come segue:
var socket = new WebSocketServer("ws://127.0.0.1:8081/");
// Dichiariamo l'oggetto 'IWebSocketConnection'
IWebSocketConnection connection = null;
socket.Start(conn =>
{
conn.OnOpen = () =>
{
// Salviamo l'oggetto conn
connection = conn;
};
conn.OnMessage = message =>
{
// Possiamo rispondere ad un messaggio utilizzando direttamente l'oggetto 'conn',
// ad esempio per implementare una risposta del server ad uno specifico messaggio:
if(message == "ping test") {
conn.Send("pong test");
}
};
conn.OnClose = () =>
{
// ...
};
});
// ...
// Per inviare un messaggio totalmente asincrono, dal server al client:
if(connection != null) {
connection.Send("Messaggio di esempio");
}
Come si vede, abbiamo potuto implementare due possibili modalità di interazione tra client e server:
-
risposta del server ad un messaggio del client: in questo caso, è sufficiente utilizzare l'oggetto
conn
all'interno del metodoOnMessage
, costruendo una risposta basata sul contenuto del messaggio ricevuto. Questo tipo di interazione consente, ad esempio, di implementare un meccanismo di polling, senza la necessità di ricorrere ad alcuna chiamata AJAX; -
invio di messaggi asincroni dal server al client: memorizzando il riferimento all'oggetto
conn
, possiamo utilizzarlo in qualsiasi momento per inviare messaggi asincroni al client. Questo tipo di interazione è quella che permette, in maniera relativamente semplice, l'invio di notifiche push dal server al client.
Connessioni sicure
Fleck supporta anche la possibilità di utilizzare una connessione cifrata per lo scambio dei messaggi tra client e server. Per sfruttare questa possibilità, dobbiamo procedere come segue:
-
utilizzare il prefisso
wss://
all'inizio dell'URI, in fase di inizializzazione dell'oggettoWebSocketServer
:
var server = new WebSocketServer("wss://123.123.123.123:8431");
-
procurarsi un certificato X509 valido, contenente una coppia di chiavi pubblica e privata, e specificarlo come segue:
server.Certificate = new X509Certificate2("certificato.pfx");
Fatto ciò, non resta che eseguire il metodo Start
come visto in precedenza, senza più doverci preoccupare della gestione della connessione sicura (dal momento che essa sarà gestita in maniera trasparente).
Fleck offre anche funzionalità di più basso livello, come la possibilità di intervenire sulla subprotocol negotiation. Per questo tipo di dettagli, rimandiamo il lettore alla documentazione ufficiale.
Altre librerie
Prima di concludere questa lezione, è bene sottolineare il fatto che Fleck non è l'unica opzione per sviluppare un WebSocket server in C#. Tra le diverse alternative, di seguito ne elenchiamo alcune tra le più significative: