我正在为网络课程实现Go Back N协议。我正在使用WaitForSingleObject来了解接收器线程上的套接字何时在其中包含数据:

int result = WaitForSingleObject(dataReady, INFINITE);


对于“返回N”,我必须一次将多个数据包发送到接收方,并处理数据,然后将ACK数据包发送回发送方。我有一个变量ExpectedSEQ,每次发送ACK时我都会增加,以便知道数据包是否到达混乱。

但是,当第一个数据包到达时,我的调试器告诉我ExpectedSEQ已经增加,但是当操作下一个数据包时,ExpectedSEQ仍然是其原始值。

有人知道为什么会这样吗?如果我这样写一个if语句

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


第二个数据包正确注册并发送一个ack。显然,这对于大于2 tho的任何数量的数据包均不起作用。

我事件尝试将整个部分(包括原始的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
}

最佳答案

究竟如何以及何时增加expectedSeq?可能涉及内存障碍问题,因此您可能需要访问关键部分内的expectedSeq(或受其他同步对象保护)或使用Interlocked API来访问变量。

例如,编译器可能正在将expectedSeq的值缓存在寄存器中,因此可能需要同步化API来防止在代码的关键区域发生这种情况。请注意,使用volatile关键字似乎有帮助,但可能还不够用(尽管它可以用于MSVC,因为Microsoft的编译器在处理volatile对象时会使用完整的内存屏障)。

我认为您需要发布更多代码,以确切说明您如何处理expectedSeq

10-05 19:49