لماذا لا تحتفظ متغيراتي بالدولة بعد waitforsingleobject؟

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

سؤال

أقوم بتنفيذ بروتوكول العودة إلى فصل الشبكات. أنا أستخدم waitforsingleObject لمعرفة متى يحتوي المقبس الموجود على مؤشر ترابط الاستقبال على بيانات بداخله:

int result = WaitForSingleObject(dataReady, INFINITE);

من أجل العودة إلى N ، يجب أن أرسل حزم متعددة إلى جهاز الاستقبال في وقت واحد ، ومعالجة البيانات ، ثم إرسال حزمة ACK إلى المرسل. لديّ متغير متوقع أقوم بزيادة في كل مرة أرسل فيها ACK حتى أعرف ما إذا كانت الحزمة تصل خارج الترتيب.

ومع ذلك ، عند وصول الحزمة الأولى ، أخبرني مصحح الأخطاء أنه تم زيادة المتوقع ، ولكن عندما يتم معالجة الحزمة التالية ، لا تزال المتوقع قيمتها الأصلية.

أي شخص لديه أي فكرة لماذا يحدث هذا؟ إذا وضعت بيان if على هذا النحو

if(recvHeader->seq == expectedSeq+1)

تسجل الحزمة الثانية بشكل صحيح وترسل ACK. من الواضح أن هذا لن ينجح مع أي كمية من الحزم أعلى من 2 ثو.

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

شكرا لمساعدتك!

إريك

لكل طلب: المزيد من الرمز!

WaitForSingleObject(semaphore, INFINITE);
int result = WaitForSingleObject(dataReady, timeout);
if(result == WAIT_TIMEOUT)
   rp->m->printf("Receiver:\tThe packet was lost on the network.\n");
else {
  int bytes = recvfrom(sock, recv_buf, MAX_PKT_SIZE, 0, 0, 0);
  if(bytes > 0) {
   rp->m->printf("Receiver:\tPacket Received\n");
   if(recvHeader->syn == 1 && recvHeader->win > 0)
       windowSize = recvHeader->win;

   //FORMER BUG: (recvHeader->syn == 1 ? expectedSeq = recvHeader->seq : expectedSeq = 0);
   if(recvHeader->syn)
      expectedSeq = recvHeader->seq;
   switch(rp->protocol) {
      case RDT3:
         ...
      break;
      case GBN:
         if(recvHeader->seq == expectedSeq) {
            GBNlastACK = expectedACK;
            //Setup sendHeader for the protocol
            sendHeader->ack = recvHeader->seq;
            ...
            sendto(sock, send_buf, sizeof(send_buf), 0, (struct sockaddr*) &send_addr, sizeof(struct sockaddr_in));
            if(sendHeader->syn == 0) { //make sure its not the first SYN connection packet
               WaitForSingleObject(mutex, INFINITE);
               expectedSeq++;
               ReleaseMutex(mutex);
               if(recvHeader->fin) {
                  fin = true;
                  rp->m->printf("Receiver:\tFin packet has been received. SendingOK\n");
               }          
            }
         }
    break;
    }//end switch
}
هل كانت مفيدة؟

المحلول 2

عندما كنت أدخل الكود الخاص بي (كتابة اليد نظرًا لأن الكود الخاص بي على جهاز كمبيوتر آخر) ، أدركت وجود خطأ غبي للغاية عندما كنت أقوم بتعيين القيمة الأصلية لـ EnterainSeQ. كنت أعمل على 0 كل تشغيل من خلال حزمة.

يجب أن تحب الرمز الذي يخرج عند الترميز حتى الساعة 5 صباحًا!

نصائح أخرى

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

على سبيل المثال ، قد يكون المترجم تخزين قيمة expectedSeq في السجل ، قد يكون من الضروري اتباع واجهات برمجة تطبيقات Synchrnoization لمنع حدوث ذلك في المناطق الحرجة من الكود. لاحظ أن باستخدام volatile قد يبدو أن الكلمة الرئيسية تساعد ، لكنها ربما لا تكون كافية تمامًا (على الرغم من أنها قد تكون مع MSVC ، لأن برنامج التحويل البرمجي لشركة Microsoft يستخدم حواجز الذاكرة الكاملة عند التعامل معها volatile أشياء).

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

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