سؤال

أنا أحاول إنشاء خادم تكراري يستند إلى مآخذ مخطط البيانات (UDP). يتواصل الاتصال بالعميل الأول الذي يحصل عليه من أول مكالمة RECVFROM () (نعم، أعرف أن هذا لا يوجد اتصال حقيقي). بعد أن خدم هذا العميل، افصل مقبس UDP (الاتصال بالتواصل مع AF_UNSPEC) ثم استدعاء RecvFrom () للحصول على الحزمة الأولى من العميل التالي.

الآن المشكلة هي أن نداء RECVFROM () في التكرار الثاني للحلقة هي إرجاع 0. لا يرسل عملاء الحزم الفارغة، فما يمكن أن يحدث.

هذا هو ما تفعله أي (pseudocode):

s = socket(PF_INET, SOCK_DGRAM, 0)

bind(s)

for(;;)
{
  recvfrom(s, header, &client_address)  // get first packet from client
  connect(s,client_address)  // connect to this client
  serve_client(s);
  connect(s, AF_UNSPEC); // disconnect, ready to serve next client
}

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

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

المحلول

الاتصال () هو حقا غير ضروري تماما على Sock_dgram.

استدعاء الاتصال لا يمنعك تلقي الحزم من المضيفين الآخرين, ، كما أنه لا يمنعك إرسالها. فقط لا تهتم، إنها ليست مفيدة حقا.

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

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

في كل الاحتمالات، كانت حزمة البايت الصفر في قائمة الانتظار بالفعل.

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

يجب أن تكون تطبيقات UDP قادرة على التعرف على حزم "القشر" وإسقاطها؛ سوف يحضر عاجلا أم آجلا.

نصائح أخرى

man connect:

... إذا لم يكن مقبس البدء وضع اتصال، فسيقوم الاتصال () بتعيين عنوان نظير المقبس، ولا يتم إجراء اتصال. بالنسبة إلى Sock_Dgram Sockets، يحدد عنوان الأقران حيث يتم إرسال جميع مخططات البيانات عند وظائف الإرسال () اللاحقة، ويحد من المرسل البعيد لوظائف Recv () اللاحقة (). إذا كان العنوان عنوانا فارغا للبروتوكول، يجب إعادة تعيين عنوان نظير المقبس. ...

مجرد تصحيح في حالة استئصال أي شخص في هذا الوقت كما لو أنني فعلت. لاحتياجات Confonnnnect Connect () التي يجب استدعاؤها باستخدام عضو SA_Family في Sockaddr المحدد إلى AF_UNSPEC. لم تمر فقط AF_UNSPEC.

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