مكتبة خفيفة الوزن تسمح لك بإرسال واستقبال الكائنات عبر TCP أو UDP. يهدف ObjectTranport إلى أن يكون إطار عمل شبكيًا بسيطًا وخفيف الوزن قدر الإمكان.
تتوفر خيارات تسلسل متعددة مثل Protobuf. التسلسل قابل للحقن ويمكنك تنفيذه بنفسك.
يتم تقسيم ObjectTransport إلى حزم منفصلة بناءً على احتياجاتك ومتاحة على nuget. يرجى الاطلاع على تعليمات التثبيت لمزيد من التفاصيل: https://github.com/RhynoVDS/ObjectTransport/wiki/Installation
يمكنك بدء تشغيل خادم TCP بالرمز التالي:
var server = ObjectTransport . Factory . CreateTCPServer ( )
. UseJSONserialization ( ) ;
. Build ( ) ;
//Start the TCP server on port 123
server . Start ( "127.0.0.1" , 123 ) ;
أو يمكنك بدء خادم UDP
var server = ObjectTransport . Factory . CreateUDPServer ( )
. UseJSONserialization ( ) ;
. Build ( ) ;
//Start the UDP server on port 123
server . Start ( "127.0.0.1" , 123 ) ;
في هذا المثال لدينا سيناريو حيث نريد التعامل مع مستخدم يقوم بتسجيل الدخول إلى الخادم. لنفترض أن لدينا فئة بسيطة تسمى "LoginModel". في الوقت الحالي، تحتوي هذه الفئة فقط على حقل "اسم المستخدم"
public class LoginModel
{
public string Username { get ; set ; }
}
نريد أن يستقبل الخادم هذا الكائن ويتعامل معه. يمكن القيام بذلك باستخدام وظيفة "الاستلام":
server . Receive < LoginModel > ( lm =>
{
Console . WriteLine ( lm . Username ) ;
} )
. Execute ( ) ;
في الكود أعلاه، نحدد أنه عندما يتلقى الخادم كائنًا من النوع "LoginModel"، قم بتنفيذ lambda المحدد. ثم نكتب اسم المستخدم على وحدة التحكم.
من الممكن إعداد وظائف تلقي متعددة والتعامل مع الأنواع الأخرى:
server . Receive < LoginModel > ( lm => .. . ) . Execute ( ) ;
server . Receive < LogOutModel > ( lm => .. . ) . Execute ( ) ;
server . Receive < PlayerPosition > ( lm => .. . ) . Execute ( ) ;
.. .
يمكنك بدء عميل TCP بالرمز التالي:
var client = ObjectTransport . Factory . CreateTCPClient ( )
. UseJSONserialization ( ) ;
. Build ( ) ;
//Start the client and connect to the target IP address and port
client . Start ( "10.0.0.1" , 123 ) ;
لإرسال كائن عبر القناة، استخدم وظيفة "إرسال":
var loginRequest = new LoginModel ( )
loginRequest . Username = "TestUser" ;
client . Send ( loginRequest ) . Execute ( ) ;
في المثال التالي، سنوضح كيف يمكن للخادم/العميل الرد على كائن مستلم.
في مثالنا السابق، نقوم حاليًا بإرسال اسم مستخدم إلى الخادم ولكن ليس كلمة المرور الخاصة بنا، وهي ليست آمنة جدًا. في هذا المثال، قمنا بتحديث نموذجنا ليحتوي على حقل "كلمة المرور":
public class LoginModel
{
public string Username { get ; set ; }
public string Password { get ; set ; }
}
يحتاج عميلنا إلى إرسال طلب تسجيل دخول إلى الخادم وسيحتاج الآن إلى إرسال كلمة المرور الخاصة به أيضًا. ونتيجة لذلك، نريد التعامل مع أي ردود على طلبنا بما في ذلك ما إذا كان تسجيل الدخول ناجحًا أم لا. للتعامل مع هذا، نقوم بإنشاء فئتين جديدتين "LoginSuccess" و"LoginFailure".
public class LoginSuccess
{
public string Name { get ; set ; }
public string Password { get ; set ; }
}
public class LoginFailure
{
public string Message { get ; set ; }
}
في كود العميل الخاص بنا، سنستخدم الآن وظيفة "الاستجابة" بعد إرسال كائن تسجيل الدخول. عندما يقوم الخادم بالرد على الكائن الذي تم إرساله، سيتعامل العميل مع استجاباته:
var transport = ObjectTransport . Factory . CreateTCPClient ( "10.0.0.1" , 123 ) ;
var loginRequest = new LoginModel ( ) ;
loginRequest . Username = "TestUser" ;
loginRequest . Password = "A password" ;
transport . Send ( loginRequest )
. Response < LoginSuccess > ( ls => {
Console . WriteLine ( "Welcome Back {0}" , ls . Name ) ;
} )
. Response < LoginFailure > ( lr => {
Console . WriteLine ( lr . Message )
} )
. Execute ( ) ;
في المثال أعلاه، قمنا بإعداد معالجين للاستجابة، أحدهما للتعامل مع "LoginSuccess" والآخر للتعامل مع "LoginFailure".
على الخادم، سنستخدم وظيفة "الرد" بعد استلام نموذج تسجيل الدخول. عند استخدام هذه الوظيفة، نحتاج إلى استخدام دالة/lambda والتي "ستعيد" الكائن الذي سيتم إرساله مرة أخرى:
server . Receive < LoginModel > ( )
. Reply ( lr => {
string user = string . empty ;
//Check if login is valid
if ( utilities . Login ( lr , out user ) )
{
//Return an object back to the client
var response = new LoginSuccess ( ) ;
response . Message = "Login Successful" ;
response . Name = user ;
return response ;
}
else
{
//Return an object back to the client
var response = new LoginFailure ( ) ;
response . Message = "Login Failed" ;
return response ;
}
} )
. Execute ( ) ;
عند اتصال عدة عملاء، من الممكن تحديد العميل الذي تريد إرسال رسالة إليه باستخدام الوظيفة "إلى". يمكنك تحديد عدة عملاء في وظيفة "إلى".
server . Send ( anObjectToSend )
. To ( client1 , client2 , .. . ClientN )
. Execute ( ) ;
يمكنك الإرسال إلى جميع العملاء باستخدام ما يلي.
//Send to all clients
server . Send ( anObjectToSend )
. ToAll ( )
. Execute ( ) ;
//Note that you don't actually need to specify ToAll anymore. By default the API will send to all
يمكنك أيضًا الإرسال إلى جميع العملاء وتحديد الأشخاص الذين سيتم استبعادهم:
//Send to all clients except client 3
server . Send ( anObjectToSend )
. ToAllExcept ( client3 ) //Can exclude more eg: .ToAllExcept(client3,client2, ... clientN)
. Execute ( ) ;
يمكنك تحديد ما يجب أن يحدث عندما يتصل شخص ما أو ينقطع الاتصال:
//Setup onconnect handler
transport . OnClientConnect ( c => Console . WriteLine ( "A client has connected with ip {0}" , c . IPAddress ) ) ;
//Setup onDisconnect handler
transport . OnClientDisconnect ( c => Console . WriteLine ( "A client has disconnected with ip {0}" , c . IPAddress ) ) ;
عند إرسال كائنات عبر UDP، يتم إرسال الرسالة دون موثوقية. يمكنك تشغيل UDP بشكل موثوق باستخدام ما يلي:
client . SetReliable ( ) ;
بعد تنفيذ السطر أعلاه، سيتم إرسال جميع الكائنات المرسلة بشكل موثوق.
هناك خيار آخر وهو إرسال رسالة محددة بشكل موثوق. وما يلي يوضح ذلك:
client . Send ( anObjectToSend )
. Reliable ( ) ;
. Execute ( ) ;
لفصل عميل واحد أو أكثر عن الخادم، يمكنك استخدام وظيفة DisconnectClient:
server . DisconnectClient ( client1 , client2 , .. . clientN ) ;