views:

61

answers:

2

I am implementing a Go Back N protocol for a networking class. I am using WaitForSingleObject to know when the socket on my receiver thread has data inside it:

int result = WaitForSingleObject(dataReady, INFINITE);

For Go Back N, I have to send multiple packets to the receiver at once, and manipulate the data, and then send an ACK packet back to the sender. I have a variable expectedSEQ that I increment each time I send an ACK so that I know if a packet arrives out of order.

However, when the first packet arrives, my debugger tells me that expectedSEQ has been incremented, but when the next packet is being manipulated, expectedSEQ is still its original value.

Anyone have any idea why this is occurring? If I put an if statement as such

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

the second packet registers properly and sends an ack. Clearly this will not work for any amount of packets higher than 2 tho.

I event tried wrapping the entire section (including the original WaitForSingleObject) in a semaphore in an attempt to make everything wait until after the variable was incremented but this didn't work either.

Thanks for your help!

Eric

Per Request: more code!

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
}
A: 

Exactly how and when do you increment expectedSeq? There may be a memory barrier issue involved, so you might need to access expectedSeq inside a critical section (or protected by some other synchronization object) or use Interlocked APIs to access the variable.

For example, the compiler might be caching the value of expectedSeq in a register, so synchrnoization APIs might be necessary to prevent that from happening at critical areas of the code. Note that using the volatile key word may seem to help, but it's also probably not entirely sufficient (though it might with MSVC, since Microsoft's compiler uses full memory barriers when dealing with volatile objects).

I think you'll need to post more code shown exactly how you're handling expectedSeq.

Michael Burr
A: 

As I was entering my code (hand typing since my code was on another computer), I realized a very stupid bug when I was setting the original value for expectedSeq. I was setting it to 0 every run through of a packet.

Have to love the code that comes out when you are coding until 5 am!

Eric Reynolds
Mark this as a solution.
Dialecticus
cant until 2 days after posting it per stackoverflow requirements
Eric Reynolds