我正在为网络类实现Go Back N协议。我正在使用WaitForSingleObject来知道我的接收器线程上的套接字何时包含数据:
int result = WaitForSingleObject(dataReady, INFINITE);
对于Go Back N,我必须立即向接收器发送多个数据包,并操纵数据,然后将ACK数据包发送回发送者。我有一个变量expectedSEQ,我每次发送一个ACK时都会递增,这样我就知道数据包是否无序到达。
然而,当第一个数据包到达时,我的调试器告诉我expectedSEQ已经递增,但是当操作下一个数据包时,expectedSEQ仍然是它的原始值。
任何人都知道为什么会这样?如果我把if语句作为这样的话
if(recvHeader->seq == expectedSeq+1)
第二个数据包正确注册并发送确认。显然,这对于任何高于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
}
答案 0 :(得分:0)
究竟是如何以及何时增加expectedSeq
的?可能涉及内存屏障问题,因此您可能需要访问关键部分内的expectedSeq
(或受其他同步对象保护)或使用Interlocked
API访问变量。
例如,编译器可能正在缓存寄存器中expectedSeq
的值,因此可能需要同步API来防止在代码的关键区域发生这种情况。请注意,使用volatile
关键字似乎有所帮助,但它也可能不完全足够(尽管它可能与MSVC一样,因为Microsoft的编译器在处理volatile
对象时使用完全内存屏障)。
我认为您需要发布更多代码,以准确显示您处理expectedSeq
的方式。
答案 1 :(得分:0)
当我输入我的代码时(由于我的代码在另一台计算机上进行手动输入),当我为expectedSeq设置原始值时,我意识到了一个非常愚蠢的错误。每次运行数据包时我都将它设置为0。
必须喜欢编码到凌晨5点时出现的代码!