Netly
v3.1.0
アクティブな開発は「dev」ブランチで行われます。安定版リリースについては、 「main」ブランチを参照してください。
Netly バージョン 4 は間もなくリリースされ、Netly と対話する新しい方法の検証に役立ちます。もっと見る
Netly 上のあなたのスターは私たちの旅を明るくし、大きな影響を与えます。 |
バージョン 4 開発ロードマップ
完全に実装 | バイト 3 • TCPクライアント• TCPサーバー• UDPクライアント• UDPサーバー• HTTPクライアント• HTTPサーバー• HTTP WebSocket • RUDPクライアント• RUDPサーバー |
---|---|
進行中の作業 | ドキュメントv4 #63 (新しいドキュメント Web サイト) HTTPボディ (Enctype 検出器およびパーサー) #67 (ミドルウェアとしてのボディ パーサー) |
保留中の機能 | Byter v4の追加※開発中 RUDP テストの追加 HTTP テストの追加 Websocket テストの追加 |
Netly と呼ばれるこのプロジェクトに関する基本情報を取得します
概要 | Netly は、ネットワーク通信を合理化するために設計された堅牢な C# ソケット ライブラリです。 HTTP、TCP、SSL/TLS、UDP、Reliable UDP (RUDP)、WebSocket などの複数のプロトコルの包括的なサポートを提供します。この多用途性により、Netly は、マルチプレイヤー ゲームやチャット システムからリアルタイム データ交換に至るまで、幅広いアプリケーションを開発するための優れた選択肢となります。 |
---|---|
Webサイト | リポジトリ: github.com/alec1o/netly ドキュメント: netly.docs.kezero.com |
スポンサー | |
サポーター | Netly に貢献する理由
|
公式出版社
ナゲット | Unity アセット ストア |
---|---|
Nuget にインストールする | アセットストアにインストールする |
注目すべき変更点
v1.xx | v2.xx | v3.xx | v4.xx |
---|---|---|---|
遺産 | 遺産 | 安定した | 発達 |
TCPのサポート | メッセージ フレーミングをサポートする TCP | TLS/SSL をサポートする TCP | HTTP クライアントとサーバーのサポート |
UDPのサポート | TCP と UDP のパフォーマンスが向上 | UDP 接続あり (タイムアウト応答) | 信頼性の高い UDP (RUDP) クライアントとサーバーのサポート |
新しいメッセージ フレーミング プロトコルとパフォーマンスの向上 | WebSocket クライアントとサーバーのサポート | ||
Byter 2.0 へのアップグレード | Byter 3.0 へのアップグレード | ||
ドキュメントフレームワークとしての Docsify | Docusaurus と DocFxMarkdownGen によるドキュメントの改善 | ||
構文と内部改善 | |||
XML コメントの改善 |
統合に関する技術的な説明
テスト済みプラットフォームのリスト |
|
---|---|
依存関係 | バイト |
建てる |
# 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/ |
特徴 |
|
コードのハイライト
TCP | クライアント 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 ) ; サーバ 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 | クライアント 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 ) ; サーバ 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 | クライアント 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 ( ) ; サーバ 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 ( ) ; 地図 // 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
*/
ミドルウェア /*
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 | クライアント 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 ) ; サーバ 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 ) ; |
ウェブソケット | クライアント 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 ) ; サーバ 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 の公式情報を参照してください。
原生的 using Byter ;
警告プリミティブは、複雑なデータ (T[]、List、Class、Struct、Enum) をシリアル化/逆シリアル化できます。
例
拡大 using Byter ;
|
統合と対話のサンプルコード
標準 | コンソール 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 ) ;
}
}
}
} |
---|---|
亜麻エンジン | スクリプト 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 ) ;
}
}
}
} |
ユニティエンジン | モノビヘイビア 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 ) ;
}
}
}
} |
警告: | イベント ハンドラーをループではなく 1 回初期化します。 `Awake()` や `Start()` などの初期化メソッドで `..On.` メソッドを使用してハンドラーを設定します。パフォーマンスを維持するために、更新ループでこれらを繰り返し設定することは避けてください。 プロトコルのアクションを賢明に処理します。 `..To.Open()`、`..To.Data()`、`..To.Close()` などの `..To.` メソッドは、慎重に管理して使用してください。接続がまだ開いていない場合にのみ接続を開き、接続がアクティブであることが確認された場合にのみデータを送信するようにしてください。これらのメソッドをタイトなループ内で呼び出すことは避けてください。 // 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]
} |