Why aren't my variables holding state after WaitForSingleObject?
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");
} 开发者_StackOverflow
}
}
break;
}//end switch
}
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
.
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!
精彩评论