¿Por qué mis variables de estado después de la celebración de WaitForSingleObject?
-
26-09-2019 - |
Pregunta
Me estoy poniendo en práctica un protocolo Retroceso N para una clase de redes. Estoy utilizando WaitForSingleObject saber cuando el socket en mi hilo receptor tiene en su interior los datos:
int result = WaitForSingleObject(dataReady, INFINITE);
Para Retroceder N, tengo que enviar múltiples paquetes al receptor a la vez, y manipular los datos, y luego enviar un paquete ACK de vuelta al remitente. Tengo un expectedSEQ variables que incrementará cada vez que se envía un ACK para que yo sepa si un paquete llega fuera de orden.
Sin embargo, cuando llega el primer paquete, mi depurador me dice que expectedSEQ se ha incrementado, pero cuando se está manipulando el siguiente paquete, expectedSEQ sigue siendo su valor original.
Alguien tiene alguna idea de por qué esto está ocurriendo? Si pongo una sentencia if como tal
if(recvHeader->seq == expectedSeq+1)
el segundo paquete registra correctamente y envía un acuse de recibo. Es evidente que esto no funcionará para cualquier cantidad de paquetes mayor que 2 Tho.
Me evento intentó envolver la sección completa (incluyendo el WaitForSingleObject original) en un semáforo en un intento de hacer que todo espera hasta después de que se incrementa la variable, pero esto no funcionaba bien.
Gracias por su ayuda!
Eric
Por la petición: más código
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
}
Solución 2
Como estaba entrando en mi código (mano escribiendo desde mi código era en otro equipo), me di cuenta de un error muy estúpido cuando yo estaba sentado el valor original para expectedSeq. Yo estaba sentado a 0 cada carrera a través de un paquete.
tiene que amar el código que sale cuando se está codificando hasta las 5 am!
Otros consejos
Exactamente cómo y cuándo te expectedSeq
de la subasta? Puede haber un problema de barrera de memoria involucrado, por lo que puede que tenga que acceder expectedSeq
dentro de una sección crítica (o protegido por algún otro objeto de sincronización) o API utilización Interlocked
acceder a la variable.
Por ejemplo, el compilador podría ser el almacenamiento en caché el valor de expectedSeq
en un registro, por lo que las API synchrnoization podrían ser necesarios para evitar que esto ocurra en áreas críticas del código. Tenga en cuenta que el uso de la palabra clave volatile
puede parecer que ayuda, pero es también, probablemente, no es del todo suficiente (aunque puede ser que con MSVC, ya que el compilador de Microsoft utiliza barreras de memoria completo cuando se trata de objetos volatile
).
creo que necesita para publicar más código que se muestra exactamente cómo se está expectedSeq
manipulación.