حول نموذج الشبكة في الألعاب للمبتدئين

حول نموذج الشبكة في الألعاب للمبتدئين
خلال الأسبوعين الماضيين ، كنت أعمل على محرك الشبكات الخاص بلعبتي. قبل ذلك ، لم أكن أعرف شيئًا عن الشبكات في الألعاب على الإطلاق ، لذلك قرأت الكثير من المقالات وقمت بالعديد من التجارب لفهم كل المفاهيم وأكون قادرًا على كتابة محرك الشبكات الخاص بي.

في هذا الدليل ، أود أن أشاركك في المفاهيم المختلفة التي تحتاج إلى تعلمها قبل كتابة محرك اللعبة الخاص بك ، بالإضافة إلى أفضل الموارد والمقالات لتعلمها.

بشكل عام ، هناك نوعان رئيسيان من معماريات الشبكة: نظير إلى نظير وخادم العميل. في بنية نظير إلى نظير (p2p) ، يتم نقل البيانات بين أي زوج من اللاعبين المتصلين ، بينما في بنية خادم العميل ، يتم نقل البيانات فقط بين اللاعبين والخادم.

على الرغم من أن بنية الند للند لا تزال مستخدمة في بعض الألعاب ، إلا أن بنية خادم العميل هي المعيار: فهي أسهل في التنفيذ ، وتتطلب عرضًا أصغر للقناة ، وتسهل الحماية من الغش. لذلك ، في هذا الدليل ، سنركز على بنية خادم العميل.

على وجه الخصوص ، نحن مهتمون أكثر بالخوادم الاستبدادية: في مثل هذه الأنظمة ، يكون الخادم دائمًا على حق. على سبيل المثال ، إذا اعتقد اللاعب أنه في (10 ، 5) وأخبره الخادم أنه في (5 ، 3) ، فيجب على العميل استبدال موقعه بالموقع الذي يبلغ عنه الخادم ، وليس العكس. يسهل استخدام الخوادم الموثوقة التعرف على الغشاشين.

هناك ثلاثة مكونات رئيسية في أنظمة شبكات الألعاب:

  • بروتوكول النقل: كيف يتم نقل البيانات بين العملاء والخادم.
  • بروتوكول التطبيق: ما ينتقل من العملاء إلى الخادم ومن الخادم إلى العملاء وبأي تنسيق.
  • منطق التطبيق: كيف يتم استخدام البيانات المرسلة لتحديث حالة العملاء والخادم.

من المهم جدًا فهم دور كل جزء والصعوبات المرتبطة به.

بروتوكول النقل

تتمثل الخطوة الأولى في اختيار بروتوكول لنقل البيانات بين الخادم والعملاء. هناك نوعان من بروتوكولات الإنترنت لهذا: TCP и UDP. ولكن يمكنك إنشاء بروتوكول النقل الخاص بك بناءً على واحد منهم أو استخدام مكتبة تستخدمه.

مقارنة بين TCP و UDP

يعتمد كل من TCP و UDP على IP. يسمح IP بإرسال حزمة من مصدر إلى جهاز استقبال ، لكنه لا يضمن أن الحزمة المرسلة ستصل إلى جهاز الاستقبال عاجلاً أم آجلاً ، وأنها ستصل إليها مرة واحدة على الأقل ، وأن تسلسل الحزم سيصل في الترتيب الصحيح. علاوة على ذلك ، يمكن أن تحتوي الحزمة فقط على حجم بيانات محدود ، معطى بالقيمة MTU.

UDP عبارة عن طبقة رقيقة أعلى IP. ومن ثم ، فإن لها نفس القيود. في المقابل ، يحتوي TCP على العديد من الميزات. يوفر اتصالاً موثوقًا مرتبًا بين عقدتين مع التحقق من الأخطاء. لذلك ، يعد TCP مناسبًا جدًا ويستخدم في العديد من البروتوكولات الأخرى ، على سبيل المثال ، في HTTP, FTP и SMTP. لكن كل هذه الميزات لها ثمن: تأخير.

لفهم سبب تسبب هذه الوظائف في حدوث زمن انتقال ، نحتاج إلى فهم كيفية عمل TCP. عندما يرسل مضيف الإرسال حزمة إلى المضيف المستلم ، فإنه يتوقع استلام إقرار (ACK). إذا لم تستلمها بعد وقت معين (بسبب فقد الحزمة أو التأكيد ، أو لسبب آخر) ، فإنها ترسل الحزمة مرة أخرى. علاوة على ذلك ، يضمن TCP استلام الحزم بالترتيب الصحيح ، لذلك حتى يتم استلام الحزمة المفقودة ، لا يمكن معالجة جميع الحزم الأخرى ، حتى لو تم استلامها بالفعل من قبل العقدة المستقبلة.

ولكن كما تفهم على الأرجح ، يعد زمن الانتقال في الألعاب متعددة اللاعبين أمرًا مهمًا للغاية ، خاصة في الأنواع النشطة مثل FPS. هذا هو السبب في أن العديد من الألعاب تستخدم UDP مع البروتوكول الخاص بها.

يمكن أن يكون البروتوكول الأصلي المستند إلى UDP أكثر كفاءة من بروتوكول TCP لأسباب مختلفة. على سبيل المثال ، يمكنه تمييز بعض الحزم على أنها موثوقة والبعض الآخر على أنها غير موثوق بها. لذلك ، فهو لا يهتم إذا وصلت الحزمة غير الموثوقة إلى المستلم. أو يمكنه معالجة تدفقات بيانات متعددة بحيث لا تؤدي الحزمة المفقودة في أحد الدفقين إلى إبطاء التدفقات الأخرى. على سبيل المثال ، قد يكون هناك سلسلة محادثات لإدخال اللاعب وخيط آخر لرسائل الدردشة. إذا فقدت رسالة محادثة ليست بيانات عاجلة ، فلن تبطئ الإدخال العاجل. أو قد ينفذ بروتوكول الملكية الموثوقية بشكل مختلف عن بروتوكول TCP ليكون أكثر كفاءة في بيئة ألعاب الفيديو.

لذا ، إذا كان TCP سيئًا ، فسنقوم ببناء بروتوكول النقل الخاص بنا استنادًا إلى UDP؟

كل شيء أكثر تعقيدًا بعض الشيء. على الرغم من أن TCP يعتبر دون المستوى الأمثل لأنظمة شبكات الألعاب ، إلا أنه يمكن أن يعمل بشكل جيد مع لعبتك المحددة ويوفر لك وقتًا ثمينًا. على سبيل المثال ، قد لا يمثل زمن الانتقال مشكلة بالنسبة للعبة تعتمد على الأدوار أو لعبة لا يمكن لعبها إلا على شبكات LAN ، حيث يكون زمن الانتقال وفقدان الحزم أقل بكثير مما يحدث على الإنترنت.

العديد من الألعاب الناجحة ، بما في ذلك World of Warcraft و Minecraft و Terraria ، تستخدم TCP. ومع ذلك ، تستخدم معظم FPS بروتوكولاتها الخاصة بناءً على UDP ، لذلك سنتحدث عنها بمزيد من التفاصيل أدناه.

إذا اخترت استخدام TCP ، فتأكد من تعطيله خوارزمية Nagle، لأنه يخزن الحزم قبل الإرسال ، مما يعني أنه يزيد من التأخير.

لمعرفة المزيد حول الاختلافات بين UDP و TCP في سياق الألعاب متعددة اللاعبين ، راجع مقالة Glenn Fiedler UDP مقابل. TCP.

بروتوكول الملكية

هل تريد إنشاء بروتوكول النقل الخاص بك ولكن لا تعرف من أين تبدأ؟ أنت محظوظ ، لأن جلين فيدلر كتب مقالتين رائعتين حول هذا الموضوع. ستجد الكثير من الأفكار الذكية فيها.

المادة الأولى شبكات لمبرمجي الألعاب 2008 ، أسهل من الثانية بناء بروتوكول شبكة لعبة 2016. أوصي بأن تبدأ بالأقدم.

كن على علم بأن Glenn Fiedler هو مؤيد كبير لاستخدام البروتوكول الخاص بك على أساس UDP. وبعد قراءة مقالاته ، من المحتمل أن تتبنى رأيه بأن TCP له عيوب خطيرة في ألعاب الفيديو ، وسوف ترغب في تنفيذ البروتوكول الخاص بك.

ولكن إذا كنت جديدًا في مجال الشبكات ، فافعل لنفسك معروفًا واستخدم TCP أو مكتبة. لتنفيذ بروتوكول النقل الخاص بك بنجاح ، عليك أن تتعلم الكثير مسبقًا.

مكتبات الشبكة

إذا كنت بحاجة إلى شيء أكثر كفاءة من TCP ، ولكنك لا تريد عناء تنفيذ البروتوكول الخاص بك والدخول في الكثير من التفاصيل ، يمكنك استخدام مكتبة الشبكة. وهناك الكثير منهم:

لم أجربهم جميعًا ، لكنني أفضل ENet لأنه سهل الاستخدام وموثوق. بالإضافة إلى ذلك ، يحتوي على وثائق واضحة ودليل تعليمي للمبتدئين.

استنتاج بروتوكول النقل

للتلخيص ، هناك بروتوكولا نقل رئيسيان: TCP و UDP. يحتوي TCP على العديد من الميزات المفيدة: الموثوقية ، والحفاظ على ترتيب الحزم ، واكتشاف الأخطاء. لا يحتوي UDP على كل ذلك ، لكن TCP ، بطبيعته ، لديه زمن انتقال عالٍ وهو أمر غير مقبول لبعض الألعاب. أي ، لضمان زمن انتقال منخفض ، يمكنك إنشاء البروتوكول الخاص بك استنادًا إلى UDP أو استخدام مكتبة تنفذ بروتوكول النقل على UDP وتكييفها لألعاب الفيديو متعددة اللاعبين.

يعتمد الاختيار بين TCP و UDP والمكتبة على عدة عوامل. أولاً ، من احتياجات اللعبة: هل تحتاج إلى زمن انتقال منخفض؟ ثانيًا ، من متطلبات بروتوكول التطبيق: هل يحتاج إلى بروتوكول موثوق؟ كما سنرى في الجزء التالي ، من الممكن إنشاء بروتوكول تطبيق يكون البروتوكول غير الموثوق فيه مناسبًا تمامًا. أخيرًا ، تحتاج أيضًا إلى التفكير في تجربة مطور محرك الشبكة.

لدي نصيحتان:

  • قم بتلخيص بروتوكول النقل قدر الإمكان من بقية التطبيق بحيث يمكن استبداله بسهولة دون إعادة كتابة جميع الكود.
  • لا تفرط في التحسين. إذا لم تكن خبيرًا في الشبكة ولم تكن متأكدًا مما إذا كنت بحاجة إلى بروتوكول النقل الخاص بك المستند إلى UDP ، فيمكنك البدء باستخدام TCP أو مكتبة توفر الموثوقية ، ثم اختبار الأداء وقياسه. إذا كنت تواجه مشكلات وكنت متأكدًا من أنه بروتوكول نقل ، فقد يكون الوقت قد حان لإنشاء بروتوكول النقل الخاص بك.

في نهاية هذا الجزء ، أوصي بأن تقرأ مقدمة في برمجة الألعاب متعددة اللاعبين Brian Hook ، الذي يغطي العديد من الموضوعات التي تمت مناقشتها هنا.

بروتوكول التطبيق

الآن بعد أن أصبح بإمكاننا تبادل البيانات بين العملاء والخادم ، نحتاج إلى تحديد البيانات المراد نقلها وبأي تنسيق.

المخطط الكلاسيكي هو أن يرسل العملاء مدخلات أو إجراءات إلى الخادم ، ويرسل الخادم حالة اللعبة الحالية إلى العملاء.

لا يرسل الخادم الحالة الكاملة ، ولكن الحالة التي تمت تصفيتها مع الكيانات القريبة من المشغل. يفعل هذا لثلاثة أسباب. أولاً ، قد تكون الحالة الإجمالية أكبر من أن يتم إرسالها بتردد عالٍ. ثانيًا ، يهتم العملاء بشكل أساسي بالبيانات المرئية والصوتية ، لأن معظم منطق اللعبة يتم محاكاته على خادم اللعبة. ثالثًا ، في بعض الألعاب ، لا يحتاج اللاعب إلى معرفة بيانات معينة ، مثل موقع العدو على الجانب الآخر من الخريطة ، لأنه بخلاف ذلك يمكنه شم الحزم ومعرفة مكان التحرك بالضبط لقتله.

التسلسل

تتمثل الخطوة الأولى في تحويل البيانات التي نريد إرسالها (الإدخال أو حالة اللعبة) إلى تنسيق مناسب للإرسال. هذه العملية تسمى التسلسل.

تتبادر الفكرة إلى الذهن على الفور لاستخدام تنسيق يمكن قراءته ، مثل JSON أو XML. لكن هذا سيكون غير فعال تمامًا وسيشغل معظم القناة مجانًا.

بدلاً من ذلك ، يوصى باستخدام التنسيق الثنائي ، وهو أكثر إحكاما. أي أن الحزم ستحتوي فقط على عدد قليل من البايت. هنا يجب أن نأخذ في الاعتبار المشكلة ترتيب البايت، والتي قد تختلف على أجهزة كمبيوتر مختلفة.

لتسلسل البيانات ، يمكنك استخدام مكتبة ، على سبيل المثال:

فقط تأكد من إنشاء المكتبة لأرشيفات محمولة وتهتم بالأمر.

قد يكون الحل البديل هو تنفيذه بنفسك ، ليس بهذه الصعوبة ، خاصة إذا كنت تستخدم نهجًا يركز على البيانات في التعليمات البرمجية الخاصة بك. بالإضافة إلى ذلك ، سيسمح لك بإجراء تحسينات ليست ممكنة دائمًا عند استخدام المكتبة.

كتب جلين فيدلر مقالتين عن التسلسل: حزم القراءة والكتابة и استراتيجيات التسلسل.

ضغط

كمية البيانات المنقولة بين العملاء والخادم محدودة بعرض النطاق الترددي للقناة. سيسمح لك ضغط البيانات بنقل المزيد من البيانات في كل لقطة ، أو زيادة معدل التحديث ، أو ببساطة تقليل متطلبات النطاق الترددي.

التعبئة بت

الأسلوب الأول هو التعبئة بت. وهو يتألف من استخدام عدد البتات الضروري لوصف القيمة المرغوبة بالضبط. على سبيل المثال ، إذا كان لديك تعداد يمكن أن يحتوي على 16 قيمة مختلفة ، فعندئذٍ بدلاً من بايت كامل (8 بت) ، يمكنك استخدام 4 بت فقط.

يشرح جلين فيدلر كيفية تنفيذ ذلك في الجزء الثاني من المقالة. حزم القراءة والكتابة.

تعمل حزم البت بشكل جيد مع التمييز ، والذي سيكون موضوع القسم التالي.

أخذ العينات

أخذ العينات هي تقنية ضغط مع فقدان البيانات تستخدم فقط مجموعة فرعية من القيم الممكنة لترميز قيمة. أسهل طريقة لتنفيذ التمييز هي تقريب أرقام الفاصلة العائمة.

يوضح جلين فيدلر (مرة أخرى!) كيفية تطبيق التقدير في الممارسة العملية في مقالته ضغط اللقطة.

خوارزميات الضغط

ستكون التقنية التالية هي خوارزميات الضغط بدون فقدان البيانات.

هنا ، في رأيي ، هي الخوارزميات الثلاث الأكثر إثارة للاهتمام التي تحتاج إلى معرفتها:

  • ترميز هوفمان مع رمز محسوب مسبقًا ، وهو سريع للغاية ويمكن أن يؤدي إلى نتائج جيدة. تم استخدامه لضغط الحزم في محرك شبكة Quake3.
  • زليب هي خوارزمية ضغط للأغراض العامة لا تزيد أبدًا من كمية البيانات. كيف ترى هنا، فقد تم استخدامه في مجموعة متنوعة من التطبيقات. لتحديث الدول ، قد تكون زائدة عن الحاجة. ولكن يمكن أن يكون مفيدًا إذا كنت بحاجة إلى إرسال أصول أو نصوص طويلة أو تضاريس للعملاء من الخادم.
  • نسخ أطوال التشغيل ربما تكون أبسط خوارزمية ضغط ، لكنها فعالة جدًا لأنواع معينة من البيانات ، ويمكن استخدامها كخطوة معالجة مسبقة قبل zlib. إنها مناسبة بشكل خاص لضغط التضاريس التي تتكون من البلاط أو وحدات البكسل التي تتكرر فيها العديد من العناصر المجاورة.

ضغط دلتا

تقنية الضغط النهائية هي ضغط دلتا. يكمن في حقيقة أنه يتم نقل الفروق بين حالة اللعبة الحالية وآخر حالة يتلقاها العميل فقط.

تم استخدامه لأول مرة في محرك شبكة Quake3. فيما يلي مقالتان تشرحان كيفية استخدامه:

استخدمها جلين فيدلر أيضًا في الجزء الثاني من مقالته. ضغط اللقطة.

التشفير

بالإضافة إلى ذلك ، قد تحتاج إلى تشفير نقل المعلومات بين العملاء والخادم. هناك عدة أسباب لذلك:

  • الخصوصية / السرية: لا يمكن قراءة الرسائل إلا من قبل المستلم ولن يتمكن أي متسلل شبكة آخر من قراءتها.
  • المصادقة: يجب على الشخص الذي يريد أن يلعب دور اللاعب أن يعرف مفتاحه.
  • منع الغش: سيكون من الأصعب بكثير على اللاعبين الخبثاء إنشاء حزم الغش الخاصة بهم ، وسيتعين عليهم تكرار مخطط التشفير والعثور على المفتاح (الذي يتغير في كل اتصال).

أوصي بشدة باستخدام مكتبة لهذا الغرض. أقترح استخدام ليبسوديوم، لأنه بسيط بشكل خاص ويحتوي على برامج تعليمية رائعة. أهمية خاصة هو البرنامج التعليمي على تبادل المفاتيح، والذي يسمح لك بإنشاء مفاتيح جديدة على كل اتصال جديد.

بروتوكول التطبيق: الخاتمة

هذا يخلص بروتوكول التطبيق. أعتقد أن الضغط اختياري تمامًا وأن قرار استخدامه يعتمد فقط على اللعبة والنطاق الترددي المطلوب. التشفير ، في رأيي ، إلزامي ، لكن في النموذج الأولي يمكنك الاستغناء عنه.

منطق التطبيق

نحن الآن قادرون على تحديث الحالة في العميل ، ولكن قد نواجه مشكلات تتعلق بوقت الاستجابة. يحتاج اللاعب ، بعد إجراء الإدخال ، إلى انتظار تحديث حالة اللعبة من الخادم لمعرفة تأثيرها على العالم.

علاوة على ذلك ، بين تحديثين حالتين ، يكون العالم ثابتًا تمامًا. إذا كان معدل تحديث الحالة منخفضًا ، فستكون الحركات متقطعة للغاية.

هناك العديد من الأساليب للتخفيف من تأثير هذه المشكلة ، وسأغطيها في القسم التالي.

تقنيات تجانس التأخير

تمت مناقشة جميع التقنيات الموضحة في هذا القسم بالتفصيل في السلسلة. متعدد اللاعبين سريع الخطى غابرييل جامبيتا. أوصي بشدة بقراءة هذه السلسلة الممتازة من المقالات. يتضمن أيضًا عرضًا توضيحيًا تفاعليًا لمعرفة كيفية عمل هذه التقنيات في الممارسة.

الأسلوب الأول هو تطبيق نتيجة الإدخال مباشرة دون انتظار استجابة من الخادم. تسمى التنبؤ من جانب العميل. ومع ذلك ، عندما يتلقى العميل تحديثًا من الخادم ، يجب عليه التحقق من صحة توقعه. إذا لم يكن الأمر كذلك ، فهو يحتاج فقط إلى تغيير حالته وفقًا لما تلقاه من الخادم ، لأن الخادم سلطوي. تم استخدام هذه التقنية لأول مرة في Quake. يمكنك قراءة المزيد عنها في المقالة. مراجعة كود محرك Quake Engine فابيان سانجلارز [ترجمة على حبري].

تُستخدم المجموعة الثانية من التقنيات لتسهيل حركة الكيانات الأخرى بين تحديثين للحالة. هناك طريقتان لحل هذه المشكلة: الاستيفاء والاستقراء. في حالة الاستيفاء ، يتم أخذ آخر حالتين ويظهر الانتقال من واحدة إلى أخرى. عيبه أنه يتسبب في جزء بسيط من التأخير ، لأن العميل يرى دائمًا ما حدث في الماضي. يتعلق الاستقراء بالتنبؤ بالمكان الذي يجب أن تستند إليه الكيانات الآن بناءً على الحالة الأخيرة التي تلقاها العميل. عيبه هو أنه إذا قام الكيان بتغيير اتجاه الحركة تمامًا ، فسيكون هناك خطأ كبير بين التوقع والموقع الحقيقي.

التقنية الأخيرة والأكثر تقدمًا والمفيدة فقط في FPS هي تعويض التأخر. عند استخدام تعويض التأخير ، يأخذ الخادم في الاعتبار تأخيرات العميل عندما يطلق النار على الهدف. على سبيل المثال ، إذا قام أحد اللاعبين بإصابة في الرأس على شاشتهم ، ولكن في الواقع كان هدفهم في موقع مختلف بسبب التأخير ، فسيكون من غير العدل حرمان اللاعب من حق القتل بسبب التأخير. لذا ، يعيد الخادم الوقت إلى الوراء إلى الوقت الذي أطلق فيه اللاعب النار لمحاكاة ما رآه اللاعب على شاشته والتحقق من وجود تصادم بين تسديدته والهدف.

كتب جلين فيدلر (كما هو الحال دائمًا!) مقالًا في عام 2004 فيزياء الشبكة (2004)، حيث وضع الأساس لمزامنة المحاكاة الفيزيائية بين الخادم والعميل. في عام 2014 كتب سلسلة جديدة من المقالات فيزياء الشبكات، حيث وصف تقنيات أخرى لمزامنة المحاكاة الفيزيائية.

يوجد أيضًا مقالان في ويكي Valve ، مصدر الشبكات متعددة اللاعبين и طرق تعويض زمن الوصول في تصميم البروتوكول داخل اللعبة وتحسينه التعامل مع تعويض التأخير.

منع الغش

هناك طريقتان رئيسيتان لمنع الغش.

أولاً ، يجعل من الصعب على المحتالين إرسال حزم ضارة. كما ذكرنا سابقًا ، يعد التشفير طريقة جيدة لتنفيذه.

ثانيًا ، يجب أن يتلقى الخادم الموثوق فقط الأوامر / الإدخال / الإجراءات. يجب ألا يكون العميل قادرًا على تغيير الحالة على الخادم بخلاف إرسال الإدخال. ثم يجب على الخادم ، في كل مرة يتلقى فيها إدخالاً ، التحقق من صلاحيته قبل تطبيقه.

منطق التطبيق: الخاتمة

أوصي بتنفيذ طريقة لمحاكاة زمن الوصول العالي ومعدلات التحديث المنخفضة بحيث يمكنك اختبار سلوك لعبتك في ظروف سيئة ، حتى عندما يكون العميل والخادم يعملان على نفس الجهاز. هذا يبسط بشكل كبير تنفيذ تقنيات تجانس التأخير.

مصادر أخرى مفيدة

إذا كنت ترغب في استكشاف موارد أخرى حول نماذج الشبكة ، فيمكن العثور عليها هنا:

  • مدونة جلين فيدلر - يستحق قراءة مدونته بالكامل ، فهناك العديد من المقالات الممتازة فيها. ومن يتم جمع كافة المقالات حول تقنيات الشبكة.
  • رهيبة لعبة الشبكات بقلم M. Fatih MAR هي قائمة شاملة بالمقالات ومقاطع الفيديو حول محركات ألعاب الفيديو الشبكية.
  • В wiki subreddit r / gamedev هناك أيضا العديد من الروابط المفيدة.

المصدر: www.habr.com

إضافة تعليق