سؤال

نحن نكتب العميل و الخادم أن تفعل (ما اعتقد كان) بسيطة جدا شبكة الاتصالات.Mulitple العملاء الاتصال إلى الملقم ثم الذي من المفترض أن إرسال البيانات مرة أخرى إلى جميع العملاء الآخرين.

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

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

ومع ذلك, لقد وجدت أنه إذا كنت تستخدم:

 rv = select(fdmax + 1, &master_list, NULL, NULL, NULL);

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

if (select(....) != -1)
{
  if (FD_SET(sockfd, &master_list))
     // handle data or disconnect
  else
     // look for data to write and write() / send() those.
}

حاولت وضع حدد استطلاع الوضع (أو السخرية مهلة قصيرة) مع:

// master list contains the sockfd from the getaddrinfo/socket/connect seq
struct timeval t;
memset(&t, 0, sizeof t);
rv = select(fdmax + 1, &master_list, NULL, NULL, &t);

ولكن وجدت أن ثم ثم العميل لم يحصل أي من البيانات الواردة.

كما أنني حاولت وضع المقبس fd أن يكون غير مؤمن ، مثل:

fcntl(sockfd, F_SETFL, O_NONBLOCK);

ولكن هذا لا يحل المشكلة:

  1. إذا موكلي select() لا struct timeval, قراءة البيانات يعمل ، لكنه لم يفرج إلى اسمحوا لي أن نبحث عن للكتابة البيانات.
  2. إذا موكلي select() لديه timeval للحصول على الاستطلاع ، ثم لم إشارات أن هناك البيانات الواردة القراءة و التطبيق تجمد التفكير لا يوجد شبكة اتصال (على الرغم من حقيقة أن جميع المكالمات وظيفة نجحت)

أي مؤشرات على الإطلاق كما أن ما يمكن أن يكون به خطأ ؟ غير أنه ليس من الممكن القيام للقراءة والكتابة على نفس المقبس (لا أصدق أن هذا صحيح).

(تحرير:الإجابة الصحيحة ، الشيء الذي تذكرت على الملقم ولكن ليس على العميل أن يكون الثاني fd_set و نسخ master_list قبل كل استدعاء حدد():

// declare and FD_ZERO read_fds:
// put sockfd in master_list

while (1)
{
   read_fds = master_list;
   select(...);

   if (FD_ISSET(read_fds))
     ....
   else
     // sleep or otherwise don't hog cpu resources
}

)

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

المحلول

كل شيء يبدو على ما يرام ما عدا الخط حيث كنت تفعل if (FD_SET(sockfd, &master_list)).لدي مشابهة جدا هيكل رمز اعتدت FD_ISSET.كنت من المفترض أن اختبار ما إذا كان يتم تعيين قائمة ، وليس إلى وضعه مرة أخرى.بخلاف ذلك لا أرى أي شيء آخر.

تحرير.أيضا, لدي التالية عن مهلة:

timeval listening_timeout;
listening_timeout.tv_sec = timeout_in_seconds;
listening_timeout.tv_usec = 0;

ربما هناك مشكلة إذا قمت بتعيين أنه إلى 0 (كما يبدو لك أن تفعل؟)

Edit2.تذكرت أنني واجهت مشكلة غريبة عندما لم أكن تطهير قراءة مجموعة بعد تحديد وخرجت وقبل دخلت عليه مرة أخرى.كان علي أن أفعل شيئا مثل:

FD_ZERO(&sockfd);
FD_SET(sockfd, &rd);

قبل أن تدخل select.لا أستطيع أن أتذكر لماذا على الرغم من.

نصائح أخرى

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

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

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

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

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