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

StackOverflow https://stackoverflow.com/questions/1609880

سؤال

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

هذا مثال على المشكلة التي تسببها عملية حسابية Nagle:

ملحوظة:راجع جدول الأوامر أدناه إذا كنت ترغب في فهم معنى هذه الأوامر.

الأول هو السفينة التي حركتها (تحركت للأمام + لليمين، وتم الاستقبال للأمام ولكن لليمين لا)

العميل يرسل الأوامر:

84796: Sending data: 2#4
84796: Sending data: 2#2
84904: Sending data: 2#3
84904: Sending data: 2#0
86187: Sending data: 2#4
86188: Sending data: 2#2
86374: Sending data: 2#3
86404: Sending data: 2#0

العميل يتلقى الأوامر:

79244: Raw receive: 3#3#4$
79244: New command: 3#3#4
79398: Raw receive: 3#3#2$3#3#3$3#3#0$
79399: New command: 3#3#2
79399: New command: 3#3#3
79399: New command: 3#3#0
80635: Raw receive: 3#3#4$
80635: New command: 3#3#4
80908: Raw receive: 3#3#2$3#3#3$3#3#0$
80908: New command: 3#3#2
80908: New command: 3#3#3
80908: New command: 3#3#0

"لحظة" مصطلح غريب لا يعني ما أحاول قوله ، ولكن هنا يبدو مقدار الوقت بالمللي ثانية بعد الأمر السابق

  1. تقدم إلى الأمام إرسال بواسطة العميل (لحظة:0)، التي استلمها العميل B (اللحظة:0)

  2. 0)، التي استلمها العميل B (اللحظة:155)

  3. توقف عن الحركة إرسال من قبل العميل أ (لحظة:108)، استلمها العميل "ب" (اللحظة:0)

  4. توقف عن تحويل إرسال بواسطة العميل A (لحظة:0)، التي استلمها العميل B (اللحظة:0)

  5. المضي قدما إرسال من قبل العميل أ (لحظة:1283)، استلمها العميل "ب" (اللحظة:1236)

  6. 1) ، تلقاها العميل ب (لحظة:273)

  7. وقف الحركة إرسال من قبل العميل أ (لحظة:186)، التي استلمها العميل "ب" (اللحظة:0)

  8. توقف عن الدوران إرسال من قبل العميل أ (لحظة:30)، استلمها العميل "ب" (اللحظة:0)

هذا هو جدول الأوامر المطابق للأوامر:

العميل-> الخادم

2# (movement info)
0) now not turning
1) now turning left
2) now turning right
3) now not moving
4) now moving forward

الخادم-> العميل

3# (movement info)
[shipId]#
0) now not turning
1) now turning left
2) now turning right
3) now not moving
4) now moving forward

لذا ، ما يمكنك رؤيته هو أن الأوامر تُحدث تمامًا بسبب "Nagle".يؤدي هذا إلى تلقي أمر إيقاف الحركة من قبل العملاء الآخرين في نفس الوقت الذي يتم فيه تلقي أمر بدء الحركة، مما يتسبب في عدم تحرك هذا اللاعب على الإطلاق.

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

هل صحيح أنه لا ينبغي عليّ تعطيل خوارزمية Nagle لهذا السبب، ويجب بدلاً من ذلك البحث عن حل آخر؟ولم لا)؟

شكرا لك مقدما.- توم

هل كانت مفيدة؟

المحلول

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

مجموعات سوكوبت (TCP_NODELAY)

نصائح أخرى

إذا كنت تريد أن تكون في أسرع وقت ممكن، فيجب عليك استخدام UDP.

ومع ذلك ، لاحظ أن TCP يوفر ضمانًا توصيل و طلب في حين أن UDP يوفر لا شيء.

يبدو أن هذه النقطة هي أ حاسم نقطة مهمة في هذا التطبيق لذا سيتعين عليك وضع آلية ترتيب أوامر الإقرار/إعادة المحاولة الخاصة بك في الأعلى.

إذا كنت تريد الاستمرار في استخدام TCP، فإن TCP__NODELAY سيساعدك.مع تقدم لعبتك، قد ينتهي بك الأمر إلى طلب تدفق من البيانات التي سيكون TCP مناسبًا لها تمامًا بدون TCP_NODELAY.

RFC1006 يضفي الطابع الرسمي على آلية لإرسال الحزم عبر دفق TCP.

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

ألقِ نظرة على RTP (الذي يعمل عبر UDP) للحصول على نهج أكثر قابلية للبقاء على الشبكة.

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

  • انعطف لليسار
  • انتظر 100 مللي ثانية
  • توقف عن الدوران

أن العميل "ب" سيرى نفس التأخير البالغ 100 مللي ثانية.إن التخزين المؤقت لـ Nagle يجعل هذا الأمر أكثر تطرفًا - ولكن سيكون هناك دائمًا ارتعاش وتأخيرات متفاوتة.

تحتاج حقًا إلى إرسال شيء مثل:

  • (أنا في الموضع X1، Y1 مع الاتجاه Z1) انعطف يسارًا
  • (أنا في الموضع X2، Y2 مع العنوان Z2) توقف عن الدوران

بحيث يقوم العملاء بإعادة المزامنة باستمرار.

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top