Le développement actif a lieu sur la branche « dev » . Pour la version stable, reportez-vous à la branche « principale » .
La version 4 de Netly sera bientôt disponible, permettant de valider la nouvelle façon d'interagir avec Netly. Voir plus
Votre étoile sur Netly illumine notre parcours et a un réel impact ! |
Feuille de route de développement de la version 4
Entièrement mis en œuvre | Octet 3 • Client TCP • Serveur TCP • Client UDP • Serveur UDP • Client HTTP • Serveur HTTP • WebSocket HTTP • Client RUDP • Serveur RUDP |
---|---|
Travaux en cours | Documentation v4 #63 (Nouveau site de documentation) Corps HTTP (détecteur et analyseur Enctype) #67 (analyseur de corps comme middleware) |
Fonctionnalités en attente | Ajout de Byter v4 *En développement Ajout de tests RUDP Ajout de tests HTTP Ajout de tests Websocket |
Obtenez des informations de base sur ce projet appelé Netly
Aperçu | Netly est une bibliothèque de sockets C# robuste conçue pour rationaliser la communication réseau. Il offre une prise en charge complète de plusieurs protocoles, notamment HTTP, TCP, SSL/TLS, UDP, Reliable UDP (RUDP) et WebSocket. Cette polyvalence fait de Netly un excellent choix pour développer une large gamme d'applications, depuis les jeux multijoueurs et les systèmes de chat jusqu'aux échanges de données en temps réel. |
---|---|
Site web | Dépôt : github.com/alec1o/netly Documentation : netly.docs.kezero.com |
Parrainer | |
Supporter | Pourquoi contribuer à Netly ?
|
Editeur officiel
Nuget | Magasin d'actifs Unity |
---|---|
Installer sur Nuget | Installer sur Asset Store |
Changements notables
v1.xx | v2.xx | v3.xx | v4.xx |
---|---|---|---|
Héritage | Héritage | Écurie | Développement |
Prise en charge TCP | TCP avec prise en charge du cadrage des messages | TCP avec prise en charge TLS/SSL | Prise en charge des clients et serveurs HTTP |
Prise en charge UDP | Augmentation des performances TCP et UDP | UDP avec connexion (réponse d'expiration) | Prise en charge fiable des clients et serveurs UDP (RUDP) |
Nouveau protocole de tramage de messages et augmentation des performances | Prise en charge des clients et serveurs WebSocket | ||
Mise à niveau vers Byter 2.0 | Mise à niveau vers Byter 3.0 | ||
Docsify comme cadre de documentation | Amélioration de la documentation par Docusaurus et DocFxMarkdownGen | ||
Syntaxe et amélioration interne | |||
Amélioration des commentaires XML |
Descriptions techniques sur les intégrations
Liste des plateformes testées |
|
---|---|
Dépendances | Byter |
Construire |
# 1. clone project
$ git clone "https://github.com/alec1o/Netly" netly
# 2. build project
$ dotnet build "netly/" - c Release - o "netly/bin/"
# NOTE:
# Netly.dll require Byter.dll because is Netly dependency
# Netly.dll and Byter.dll have on build folder <netly-path>/bin/ |
Caractéristiques |
|
Points saillants du code
TCP | Client using Netly ;
TCP . Client client = new TCP . Client ( framing : true ) ; client . On . Open ( ( ) =>
{
printf ( "connection opened" ) ;
} ) ;
client . On . Close ( ( ) =>
{
printf ( "connetion closed" ) ;
} ) ;
client . On . Error ( ( exception ) =>
{
printf ( "connection erro on open" ) ;
} ) ;
client . On . Data ( ( bytes ) =>
{
printf ( "connection receive a raw data" ) ;
} ) ;
client . On . Event ( ( name , data ) =>
{
printf ( "connection receive a event" ) ;
} ) ;
client . On . Modify ( ( socket ) =>
{
printf ( "called before try open connection." ) ;
} ) ;
client . On . Encryption ( ( certificate , chain , errors ) =>
{
// Only if client.IsEncrypted is enabled
printf ( "validate ssl/tls certificate" ) ;
// return true if certificate is valid
return true ;
} ) ; // open connection if closed
client . To . Open ( new Host ( "127.0.0.1" , 8080 ) ) ;
// close connection if opened
client . To . Close ( ) ;
// send raw data if connected
client . To . Data ( new byte [ 2 ] { 128 , 255 } ) ;
client . To . Data ( "hello world" , NE . Encoding . UTF8 ) ;
// send event if connected
client . To . Event ( "name" , new byte [ 2 ] { 128 , 255 } ) ;
client . To . Event ( "name" , "hello world" , NE . Encoding . UTF8 ) ;
// enable encryption (must call before client.To.Open)
client . To . Encryption ( true ) ; Serveur using Netly ;
TCP . Server server = new TCP . Server ( framing : true ) ; server . On . Open ( ( ) =>
{
printf ( "connection opened" ) ;
} ) ;
server . On . Close ( ( ) =>
{
printf ( "connection closed" ) ;
} ) ;
server . On . Error ( ( exception ) =>
{
printf ( "connection error on open" ) ;
} ) ;
server . On . Accept ( ( client ) =>
{
client . On . Modify ( ( socket ) =>
{
printf ( "modify client socket e.g Enable NoDelay" ) ;
} ) ;
client . On . Open ( ( ) =>
{
printf ( "client connected" ) ;
} ) ;
client . On . Data ( ( bytes ) =>
{
printf ( "client receive a raw data" ) ;
} ) ;
client . On . Event ( ( name , bytes ) =>
{
printf ( "client receive a event" ) ;
} ) ;
client . On . Close ( ( ) =>
{
printf ( "client disconnected" ) ;
} ) ;
} ) ;
server . On . Modify ( ( socket ) =>
{
printf ( "called before try open connection." ) ;
} ) ; // open connection
server . To . Open ( new Host ( "1.1.1.1" , 1111 ) ) ;
// close connection
server . To . Close ( ) ;
// enable encryption support (must called before server.To.Open)
server . To . Encryption ( enable : true , @mypfx , @mypfxpassword , SslProtocols . Tls12 ) ;
// broadcast raw data for all connected client
server . To . DataBroadcast ( "text buffer" ) ;
server . To . DataBroadcast ( new byte [ ] { 1 , 2 , 3 } ) ;
// broadcast event (netly event) for all connected client
server . To . EventBroadcast ( "event name" , "text buffer" ) ;
server . To . EventBroadcast ( "event name" , new byte [ ] { 1 , 2 , 3 } ) ; |
---|---|
UDP | Client using Netly ;
UDP . Client client = new UDP . Client ( ) ; client . On . Open ( ( ) =>
{
printf ( "connection opened" ) ;
} ) ;
client . On . Close ( ( ) =>
{
printf ( "connection closed" ) ;
} ) ;
client . On . Error ( ( exception ) =>
{
printf ( "connection error on open" ) ;
} ) ;
client . On . Data ( ( bytes ) =>
{
printf ( "connection received a raw data" ) ;
} ) ;
client . On . Event ( ( name , eventBytes ) =>
{
printf ( "connection received a event" ) ;
} ) ;
client . On . Modify ( ( socket ) =>
{
printf ( "called before try open connection." ) ;
} ) ; // open connection if closed
client . To . Open ( new Host ( "127.0.0.1" , 8080 ) ) ;
// close connection if opened
client . To . Close ( ) ;
// send raw data if connected
client . To . Data ( new byte [ 2 ] { 128 , 255 } ) ;
client . To . Data ( "hello world" , NE . Encoding . UTF8 ) ;
// send event if connected
client . To . Event ( "name" , new byte [ 2 ] { 128 , 255 } ) ;
client . To . Event ( "name" , "hello world" , NE . Encoding . UTF8 ) ; Serveur using Netly ;
UDP . Server server = new UDP . Server ( ) ; server . On . Open ( ( ) =>
{
printf ( "connection opened" ) ;
} ) ;
server . On . Close ( ( ) =>
{
printf ( "connection closed" ) ;
} ) ;
server . On . Error ( ( exception ) =>
{
printf ( "connection error on open" ) ;
} ) ;
server . On . Accept ( ( client ) =>
{
client . On . Open ( ( ) =>
{
printf ( "client connected" ) ;
} ) ;
client . On . Close ( ( ) =>
{
// Only if use connection is enabled.
printf ( "client disconnected" ) ;
} ) ;
client . On . Data ( ( bytes ) =>
{
printf ( "client received a raw data" ) ;
} ) ;
client . On . Event ( ( name , bytes ) =>
{
printf ( "client received a event" ) ;
} ) ;
} ) ; // open connection
server . To . Open ( new Host ( "127.0.0.1" , 8080 ) ) ;
// close connection
server . To . Close ( ) ;
// broadcast raw data for all connected client
server . To . DataBroadcast ( "text buffer" ) ;
server . To . DataBroadcast ( new byte [ ] { 1 , 2 , 3 } ) ;
// broadcast event (netly event) for all connected client
server . To . EventBroadcast ( "event name" , "text buffer" ) ;
server . To . EventBroadcast ( "event name" , new byte [ ] { 1 , 2 , 3 } ) ;
|
HTTP | Client using Netly ;
HTTP . Client client = new HTTP . Client ( ) ;
// add http header for request
client . Headers . Add ( "Content-Type" , "json" ) ;
client . Headers . Add ( "Token" , "ImGui.h" ) ;
// add http url queries e.g: https://www.alec1o.com/?page=about&version=4
client . Queries . Add ( "page" , "about" ) ;
client . Queries . Add ( "version" , "4" ) ;
// set request timeout (ms) default 15s (15000ms), 0 or negative value means infinite timeout.
client . Timeout = 6000 ; // 6s
// is opened: while is requesting
bool isFetching = client . IsOpened ; HttpClient http = null ;
// called before try connect to server
// modify the HttpClient object
client . On . Modify ( ( HttpClient instance ) =>
{
http = instance ;
} ) ;
// connection is opened and fetch server.
client . On . Open ( ( response ) =>
{
// you can use "http" instance on this scope (isn't null)
if ( http . < foo > == < bar > ) { .. . }
} ) ;
// erro on fetch, it can be timeout or whatever error
// but if you receives error it mean the operation is called or done
client . On . Error ( ( Exception exception ) =>
{
Ny . Logger . PushError ( exception ) ;
} ) ;
// connection is closed with fetch server.
client . On . Close ( ( ) =>
{
if ( http . < bar > == < foo > ) { .. . }
} ) ; // used to fetch a server
client . To . Open ( "method e.g GET" , "url" , "body, allow null" ) ;
// used for cancel opened request
client . To . Close ( ) ; Serveur using Netly ;
HTTP . Server server = new HTTP . Server ( ) ;
// return true if server is serve http context
bool isServe = server . IsOpened ; server . On . Open ( ( ) =>
{
// http server opened
} ) ;
server . On . Close ( ( ) =>
{
// http server closed
} ) ;
server . On . Error ( ( exception ) =>
{
// http server open error
} ) ;
server . On . Modify ( ( httpListener ) =>
{
// HttpListener instance, called before try open connection.
} ) ;
// Open http server connection
server . To . Open ( new Uri ( "http://127.0.0.1:8080/" ) ) ;
// Close http server connection
server . To . Close ( ) ; Carte // Map path
server . Map . Get ( "/" , async ( req , res ) => {
// Handle async: GET
} )
server . Map . Post ( "/user" , ( req , res ) => {
// Handle sync: POST
} ) ;
// map using dynamic URL
server . Map . Delete ( "/post/{userId}/group/{groupId}" , async ( req , res ) ) =>
{
string userId = req . Param [ "userId" ] ;
string groupId = req . Param [ "groupId" ] ;
// Handle async: Delete from dynamic URL path
} ) ;
server . Map . WebSocket ( "/echo" , ( req , ws ) =>
{
// Handle websocket connection from path
} ) ;
/*
You can map:
* Get # get request
* Post # post request
* Delete # delete request
* Put # put request
* Patch # patch request
* Trace # trace request
* Options # options request
* Head # head request, (only head)
* All # all http nethod request
* WebSocket # websocket request
*/
Intergiciel /*
Note: Middlewares is executed in added order
*/
// Global Middleware (*don't have workflow path)
server . Middleware . Add ( async ( req , res , next ) => {
// verify request timer
Stopwatch watch = new Stopwatch ( ) ; // init timer
next ( ) ; // call another middleware.
watch . Stop ( ) ; // stop timer
res . Header . Add ( "Request-Timer" , watch . ElapsedMilliseconds . ToString ( ) ) ;
} ) ;
// Local middleware (have workflow path)
server . Middleware . Add ( "/admin" , async ( req , res , next ) => {
if ( MyApp . CheckAdminByHeader ( req . Header ) )
{
res . Header . Add ( "Admin-Token" , MyApp . RefreshAdminHeaderToken ( req ) ) ;
// call next middleware
next ( ) ;
// now. all middleware is executed. (because this is two way middleware)
res . Header . Add ( "Request-Delay" , ( DateTime . UtcNow - timer ) ( ) ) ;
}
else
{
res . Header . Add ( "Content-Type" , "application/json;charset=UTF-8" ) ;
await res . Send ( 404 , "{ 'error': 'invalid request.' }" ) ;
// skip other middlewares:
// next();
}
} ) ; |
RUDP | Client using Netly ;
RUDP . Client client = new RUDP . Client ( ) ; client . On . Open ( ( ) =>
{
printf ( "connection opened" ) ;
} ) ;
client . On . Close ( ( ) =>
{
printf ( "connection closed" ) ;
} ) ;
client . On . Error ( ( exception ) =>
{
printf ( "connection error on open" ) ;
} ) ;
client . On . Data ( ( bytes , type ) =>
{
printf ( "connection received a raw data" ) ;
} ) ;
client . On . Event ( ( name , bytes , type ) =>
{
printf ( "connection received a event" ) ;
} ) ;
client . On . Modify ( ( socket ) =>
{
printf ( "called before try open connection." ) ;
} ) ; // open connection if closed
client . To . Open ( new Host ( "127.0.0.1" , 8080 ) ) ;
// close connection if opened
client . To . Close ( ) ;
// send raw data if connected
client . To . Data ( new byte [ 2 ] { 128 , 255 } , RUDP . Unreliable ) ;
client . To . Data ( "hello world" , NE . Encoding . UTF8 , RUDP . Reliable ) ;
// send event if connected
client . To . Event ( "name" , new byte [ 2 ] { 128 , 255 } , RUDP . Unreliable ) ;
client . To . Event ( "name" , "hello world" , NE . Encoding . UTF8 , RUDP . Reliable ) ; Serveur using Netly ;
RUDP . Server server = new RUDP . Server ( ) ; server . On . Open ( ( ) =>
{
printf ( "connection opened" ) ;
} ) ;
server . On . Close ( ( ) =>
{
printf ( "connection closed" ) ;
} ) ;
server . On . Error ( ( exception ) =>
{
printf ( "connection error on open" ) ;
} ) ;
server . On . Accept ( ( client ) =>
{
client . On . Open ( ( ) =>
{
printf ( "client connected" ) ;
} ) ;
client . On . Close ( ( ) =>
{
// Only if use connection is enabled.
printf ( "client disconnected" ) ;
} ) ;
client . On . Data ( ( bytes , type ) =>
{
if ( type == RUDP . Reliable ) { .. . }
else if ( type == RUDP . Unreliable ) { .. . }
else { .. . } /* type == RUDP.Sequenced */
printf ( "client received a raw data" ) ;
} ) ;
client . On . Event ( ( name , type ) =>
if ( type == RUDP . Reliable ) { .. . }
else if ( type == RUDP . Unreliable ) { .. . }
else { .. . } /* type == RUDP.Sequenced */
printf ( "client received a event" ) ;
} ) ;
} ) ; // open connection
server . To . Open ( new Host ( "127.0.0.1" , 8080 ) ) ;
// close connection
server . To . Close ( ) ;
// broadcast raw data for all connected client
server . To . DataBroadcast ( "text buffer" , RUDP . Unreliable ) ;
server . To . DataBroadcast ( new byte [ ] { 1 , 2 , 3 } , RUDP . Reliable ) ;
server . To . DataBroadcast ( new byte [ ] { 3 , 2 , 1 } , RUDP . Sequenced ) ;
// broadcast event (netly event) for all connected client
server . To . EventBroadcast ( "event name" , "text buffer" , RUDP . Unreliable ) ;
server . To . EventBroadcast ( "event name" , new byte [ ] { 1 , 2 , 3 } , RUDP . Reliable ) ;
server . To . EventBroadcast ( "event name" , new byte [ ] { 3 , 2 , 1 } , RUDP . Sequenced ) ; |
WebSocket | Client using Netly ;
HTTP . WebSocket client = new HTTP . WebSocket ( ) ; client . On . Open ( ( ) =>
{
// websocket connection opened
} ) ;
client . On . Close ( ( ) =>
{
// websocket connection closed
} ) ;
client . On . Error ( ( exception ) =>
{
// error on open websocket connectin
} ) ;
client . On . Data ( ( bytes , type ) =>
{
if ( type == HTTP . Binary ) { .. . }
else if ( type == HTTP . Text ) { .. . }
else { /* NOTE: it's imposible */ }
// raw data received from server
} ) ;
client . On . Event ( ( name , bytes , type ) =>
{
if ( type == HTTP . Binary ) { .. . }
else if ( type == HTTP . Text ) { .. . }
else { /* NOTE: it's imposible */ }
// event received from server
} ) ;
client . On . Modify ( ( wsSocket ) =>
{
// modify websocket socket
} ) ; // open websocket client connection
client . To . Open ( new Uri ( "ws://127.0.0.1:8080/echo" ) ) ;
// close websocket client connection
client . To . Close ( ) ;
// send raw data for server
// text message
client . To . Data ( "my message" , HTTP . Text ) ;
// binnary message
client . To . Data ( NE . GetBytes ( "my buffer" ) , HTTP . Binary ) ;
// send event (netly event) for server
// text message
client . To . Event ( "event name" , "my message" , HTTP . Text ) ;
// binnary message
client . To . Data ( "event name" , NE . GetBytes ( "my buffer" ) , HTTP . Binary ) ; Serveur using Netly ;
using Netly . Interfaces ;
HTTP . Server server = new HTTP . Server ( ) ;
IHTTP . WebSocket [ ] Clients = server . WebSocketClients ; server . Map . WebSocket ( "/chat/{token}" , async ( req , ws ) =>
{
// Accept websocket from dynamic path
string token = req . Params [ "token" ] ;
// validate websocket connection from params
if ( Foo . Bar ( token ) == false )
{
ws . To . Close ( ) ;
}
ws . On . Modify ( .. . ) ;
ws . On . Open ( .. . ) ;
ws . On . Close ( .. . ) ;
ws . On . Data ( .. . ) ;
ws . On . Event ( .. . ) ;
} ) ;
server . Map . Websocket ( "/echo" , ( req , ws ) =>
{
// Handle websocket on /echo path
ws . On . Modify ( ( wsSocket ) =>
{
// modify server-side websocket ocket
} ) ;
ws . On . Open ( ( ) =>
{
// server-side websocket connection opened
} ) ;
ws . On . Close ( ( ) =>
{
// server-side websocket connection closed
} ) ;
ws . On . Data ( ( bytes , type ) =>
{
if ( type == HTTP . Binary ) { .. . }
else if ( type == HTTP . Text ) { .. . }
else { /* NOTE: it's imposible */ }
// server-side websocket received raw data
} ) ;
ws . On . Event ( ( name , bytes , type ) =>
{
if ( type == HTTP . Binary ) { .. . }
else if ( type == HTTP . Text ) { .. . }
else { /* NOTE: it's imposible */ }
// server-side websocket received event
} ) ;
} ) ; server . On . Open ( ( ) =>
{
// http server opened
} ) ;
server . On . Close ( ( ) =>
{
// http server closed
} ) ;
server . On . Error ( ( exception ) =>
{
// http server open error
} ) ;
server . On . Modify ( ( httpListener ) =>
{
// HttpListener instance, called before try open connection.
} ) ;
// Open http server connection
server . To . Open ( new Uri ( "http://127.0.0.1:8080/" ) ) ;
// Close http server connection
server . To . Close ( ) ; // open websocket client connection
server . To . Open ( new Uri ( "ws://127.0.0.1:8080/echo" ) ) ;
// close websocket client connection
server . To . Close ( ) ;
// broadcast raw data for all connected websocket socket
// text message
server . To . WebsocketDataBroadcast ( "my message" , HTTP . Text ) ;
// binnary message
server . To . WebsocketDataBroadcast ( NE . GetBytes ( "my buffer" ) , HTTP . Binary ) ;
// broadcast event (netly event) for all connected websocket socket
// text message
server . To . WebsocketEventBroadcast ( "event name" , "my message" , HTTP . Text ) ;
// binnary message
server . To . WebsocketEventBroadcast ( "event name" , NE . GetBytes ( "my buffer" ) , HTTP . Binary ) ; |
Byter | Pour plus d'informations et de détails, consultez les informations officielles de Byter
Primitif using Byter ;
Avertissement Primitive peut sérialiser/désérialiser des données complexes, par exemple (T[], List, Class, Struct, Enum).
Exemple
Extension using Byter ;
|
Exemples de codes d'intégration et d'interaction
Standard | Console using System ;
using Netly ;
public class Program
{
private static void Main ( string [ ] args )
{
UDP . Client client = new UDP . Client ( ) ;
client . On . Open ( ( ) =>
{
Console . WriteLine ( < some - text - here > ) ;
} ;
client . On . Close ( ( ) =>
{
Console . WriteLine ( < some - text - here > ) ;
} ;
client . On . Error ( ( exception ) =>
{
Console . WriteLine ( < some - text - here > ) ;
} ;
while ( true )
{
if ( ! client . IsOpened )
{
client . To . Open ( new Host ( "1.1.1.1" , 1111 ) ) ;
}
else
{
Console . WriteLine ( "Message: " ) ;
string message = Console . ReadLine ( ) ;
client . To . Data ( message ?? "No message." , NE . Encoding . UTF8 ) ;
}
}
}
} |
---|---|
Moteur de lin | Scénario using System ;
using FlaxEngine ;
using Netly ;
public class Example : Script
{
public string message ;
internal UDP . Client client ;
public override void Awake ( )
{
client = new UDP . Client ( ) ;
client . On . Open ( ( ) =>
{
Debug . Log ( < some - text - here > ) ;
} ;
client . On . Close ( ( ) =>
{
Debug . Log ( < some - text - here > ) ;
} ;
client . On . Error ( ( exception ) =>
{
Debug . Log ( < some - text - here > ) ;
} ;
}
public override void Start ( )
{
client . To . Open ( new Host ( "1.1.1.1" , 1111 ) ) ;
}
public override void Update ( )
{
if ( ! client . IsOpened )
{
client . To . Open ( new Host ( "1.1.1.1" , 1111 ) ) ;
}
else
{
if ( Input . GetKeyDown ( KeyCode . Space ) )
{
client . To . Data ( message ?? "No message." , NE . Encoding . UTF8 ) ;
}
}
}
} |
Moteur Unitaire | MonoComportement using System ;
using FlaxEngine ;
using Netly ;
public class Example : MonoBehaviour
{
public string message ;
internal UDP . Client client ;
private void Awake ( )
{
client = new UDP . Client ( ) ;
client . On . Open ( ( ) =>
{
Debug . Log ( < some - text - here > ) ;
} ;
client . On . Close ( ( ) =>
{
Debug . Log ( < some - text - here > ) ;
} ;
client . On . Error ( ( exception ) =>
{
Debug . Log ( < some - text - here > ) ;
} ;
}
private void Start ( )
{
client . To . Open ( new Host ( "1.1.1.1" , 1111 ) ) ;
}
private void Update ( )
{
if ( ! client . IsOpened )
{
client . To . Open ( new Host ( "1.1.1.1" , 1111 ) ) ;
}
else
{
if ( Input . GetKeyDown ( KeyCode . Space ) )
{
client . To . Data ( message ?? "No message." , NE . Encoding . UTF8 ) ;
}
}
}
} |
AVERTISSEMENT: | Initialisez les gestionnaires d'événements une fois, pas en boucles . Configurez des gestionnaires avec les méthodes `..On.` dans les méthodes d'initialisation comme `Awake()` ou `Start()`. Évitez de les configurer à plusieurs reprises dans des boucles de mise à jour pour maintenir les performances. Gérez judicieusement les actions protocolaires . Utilisez les méthodes `..To.`, telles que `..To.Open()`, `..To.Data()` et `..To.Close()`, avec une gestion minutieuse. Assurez-vous d'ouvrir une connexion uniquement lorsqu'elle n'est pas déjà ouverte et d'envoyer des données uniquement lorsque la connexion est confirmée comme active. Évitez d'appeler ces méthodes en boucles serrées. // OK 100% Recommended
private void Start ( )
{
var client = .. . ;
client . On . Open ( ( ) => .. . ) ; // e.g generic handler
client . On . Open ( ( ) => .. . ) ; // e.g only to send "Hi"
client . On . Event ( ( name , bytes , ? ) => .. . ) ; // e.g generic event handler
client . On . Event ( ( name , bytes , ? ) => .. . ) ; // e.g only to handle A event
client . On . Event ( ( name , bytes , ? ) => .. . ) ; // e.g only to handle B event
client . To . Open ( .. . ) ;
} public void Update ( )
{
client . To . Open ( .. . ) ; // [OK? - May Not In Loop?]
client . To . Data ( .. . ) ; // [OK? - May Not In Loop?]
client . To . Event ( .. . ) ; // [OK? - May Not In Loop?]
client . To . Close ( .. . ) ; // [OK? - May Not In Loop?]
ws . On . Open ( ( ) => .. . ) ; // [BAD - Never In Loop]
ws . On . Close ( ( ) => .. . ) ; // [BAD - Never In Loop]
ws . On . Data ( ( bytes ) => .. . ) ; // [BAD - Never In Loop]
ws . On . Error ( ( exception ) => .. . ) ; // [BAD - Never In Loop]
ws . On . Event ( ( name , bytes ) => .. . ) ; // [BAD - Never In Loop]
} |