Почему мои переменные не хотят состояния после WaitForsingleObject?
-
26-09-2019 - |
Вопрос
Я реализую протокол Go Back N для сетевого класса. Я использую WaitForsingleObject, чтобы узнать, когда розетка на моем ресивере нить имеет данные внутри него:
int result = WaitForSingleObject(dataReady, INFINITE);
Для возврата назад я должен сразу прислать несколько пакетов в приемник и манипулировать данными, а затем отправить пакет ACK обратно в отправителя. У меня есть переменная ожидаемоеeq, которое я увеличиваю каждый раз, когда я отправляю ACK так, чтобы я знаю, если пакет поступает из строя.
Однако, когда прибытие первого пакета, мой отладчик говорит мне, что ожидаемый пояс был увеличен, но когда следующий пакет манипулируется, ожидаемое пояснение, по-прежнему его первоначальное значение.
У кого-нибудь есть идеи, почему это происходит? Если я положил, если утверждение как такое
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
}
Решение 2
Когда я входил в мой код (рука, набрав, поскольку мой код был на другом компьютере), я понял очень глупую ошибку, когда я устанавливаю исходное значение для ожидаемых пояс. Я устанавливал его до 0 каждый пробег через пакет.
Должны любить код, который выходит, когда вы кодируете до 5 часов утра!
Другие советы
Как именно и когда вы увеличиваете expectedSeq
? Вовлечена проблема барьера памяти, поэтому вам может потребоваться доступ к доступу expectedSeq
внутри критического раздела (или защищены какой-либо другой объект синхронизации) или использовать Interlocked
API для доступа к переменной.
Например, компилятор может быть кэшировать значение expectedSeq
В реестре, поэтому API на синхронизации могут быть необходимы для предотвращения этого в критически важных областях кода. Обратите внимание, что используя volatile
Ключевое слово может по-видимому, помогло, но он также, вероятно, не совсем достаточно (хотя он может с MSVC, поскольку компилятор Microsoft использует полные барьеры памяти при работе с volatile
объекты).
Я думаю, вам нужно будет опубликовать больше кода, показанного именно так, как вы обрабатываете expectedSeq
.