2017-03-27 8 views
0

GoBackN 프로토콜을 구현하려고하는데 서버가 패킷을 버리면 내 경보는 이전에 보낸 모든 패킷을 보내기 전에 2 초 동안 대기합니다.alarm();을 사용하여 타임 아웃 루프에 멈춤.

알람이 작동하고 2 초 동안 기다렸지 만 첫 번째 시간 초과 후, 사용중인 상태 시스템이 루프에 걸려 시간 초과가 계속됩니다. errno이 재설정되지 않기 때문에 발생했을 수도 있지만 확실하지 않습니다.

#define TIMEOUT_SECS 2 
#define MAXTRIES 10 
int base = 0; 
int windowSize = 7; 
int sendFlag = 1; 
int tries = 0; 

int numPackets = 0; 
packet *packetArray[30]; 

void addPacket(packet *p) 
{ 
    for (int i = 0; i < 30; i++) 
    { 
     if (packetArray[i]) 
     { 
      continue; 
     } 
     else 
     { 
      packetArray[i] = p; 
      numPackets++; 
      break; 
     } 
    } 
} 

void 
CatchAlarm(int ignored) /* Handler for SIGALRM */ 
{ 
    tries += 1; 
    errno = 0; 
} 

void 
DieWithError() 
{ 
    printf("error"); 
    exit (1); 
} 

int 
max(int a, int b) 
{ 
    if (b > a) 
    return b; 
    return a; 
} 

int 
min(int a, int b) 
{ 
    if(b>a) 
    return a; 
    return b; 
} 

typedef enum 
{ 
    wait, 
    sendData, 
    timeout, 
    receiveData 
} e_state; 


int main(int argumentCount, char *argumentVariables[]) 
{ 

    //Grabbing all input information. 
    struct hostent *emulatorName; 
    emulatorName = gethostbyname(argumentVariables[1]); 
    int receiveFromEmulator = atoi(argumentVariables[3]); 
    int sendToEmulator = atoi(argumentVariables[2]); 

    //Setting up UDP socket for receiving from emulator. 
    int receiveSocket = 0; 
    receiveSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 

    //UDP socket configuration. 
    struct sockaddr_in receiveSocketStruct; 
    bzero((char *) &receiveSocketStruct, sizeof(receiveSocketStruct)); 
    receiveSocketStruct.sin_family = AF_INET; 
    receiveSocketStruct.sin_port = htons(receiveFromEmulator); 
    receiveSocketStruct.sin_addr.s_addr = INADDR_ANY; 
    socklen_t receiveSocketLen = sizeof(receiveSocketStruct); 

    //Binding UDP socket so client can locate emulator. 
    bind(receiveSocket, (struct sockaddr *)&receiveSocketStruct, sizeof(receiveSocketStruct)); 

    //Setting up UDP socket for sending to emulator. 
    int sendSocket = 0; 
    sendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 

    //UDP socket configuration. 
    struct sockaddr_in sendSocketStruct; 
    bzero((char *) &sendSocketStruct, sizeof(sendSocketStruct)); 
    sendSocketStruct.sin_family = AF_INET; 
    sendSocketStruct.sin_port = htons(sendToEmulator); 
    sendSocketStruct.sin_addr.s_addr = INADDR_ANY; 
    socklen_t sendSocketLen = sizeof(sendSocketStruct); 

    char buffer[1024]; 

    std::ifstream infile (argumentVariables[4], std::ifstream::binary); 
    infile.seekg (0, infile.end); 
    int lengthOfFile = infile.tellg(); 
    infile.seekg (0, infile.beg); 

    int totalPackets = 0; 
    int nextSeqNum = 0; 
    while(1) 
    { 
     if (lengthOfFile > 30) 
     { 
      bzero(buffer, 1024); 
      char * data = new char[1024]; 
      infile.read(buffer, 30); 
      strncpy(data, buffer, 1024); 
      lengthOfFile -= 30; 
      if (nextSeqNum > 7) 
      { 
       nextSeqNum = 0; 
      } 
      addPacket(new packet(1, nextSeqNum, strlen(data), data)); 
      totalPackets++; 
      nextSeqNum++; 
     } 
     else 
     { 
      bzero(buffer, 1024); 
      char * data = new char[1024]; 
      infile.read(buffer, 30); 
      strncpy(data, buffer, 1024); 
      if (nextSeqNum > 7) 
      { 
       nextSeqNum = 0; 
      } 
      addPacket(new packet(1, nextSeqNum, strlen(data), data)); 
      totalPackets++; 
      nextSeqNum++; 
      addPacket(new packet(3, nextSeqNum, 0, NULL)); 
      totalPackets++; 
      break; 
     } 
    } 

    infile.close(); 

    nextSeqNum = 0; 
    int packetsReceived; 
    int sentPackets; 
    int receive = 0; 
    char receivePayload[1024]; 
    char sendPayload[1024]; 

    struct sigaction myAction; /* For setting signal handler */ 
    myAction.sa_handler = CatchAlarm; 
    if (sigfillset (&myAction.sa_mask) < 0) /* block everything in handler */ 
     DieWithError(); 
    myAction.sa_flags = 0; 
    if (sigaction (SIGALRM, &myAction, 0) < 0) 
     DieWithError(); 

    e_state currentState = wait; 
    e_state previousState = wait; 

    while(1) 
    { 
     if (currentState == wait) 
     { 
      if (sendFlag == 1) 
      { 
       previousState = currentState; 
       currentState = sendData; 
      } 
      else 
      { 
       previousState = currentState; 
       currentState = receiveData; 
      } 
     } 
     else if (currentState == sendData) 
     { 
      if ((nextSeqNum < base + windowSize) && (nextSeqNum < totalPackets - 1)) 
      { 
       //send packet with seqnum. 
       int sendPacket = 0; 
       bzero(sendPayload, 1024); 
       packet * sendpckt = packetArray[nextSeqNum]; 
       sendpckt->serialize(sendPayload); 
       sendpckt->printContents(); 
       sendPacket = sendto(sendSocket, sendPayload, sizeof(sendPayload), 0, (struct sockaddr *)&sendSocketStruct, sendSocketLen); 

       if (base == nextSeqNum) 
       { 
        alarm(0); 
        alarm(TIMEOUT_SECS); 
       } 
       nextSeqNum++; 
      } 
      else 
      { 
       sendFlag = 0; 
       previousState = currentState; 
       currentState = wait; 
      } 
     } 
     else if (currentState == timeout) 
     { 
      alarm(0); 
      alarm(TIMEOUT_SECS); 

      for(int counter = base; counter < nextSeqNum; counter++) 
      { 
       int sendPacket = 0; 
       bzero(sendPayload, 1024); 
       packet * sendpckt = packetArray[counter]; 
       sendpckt->serialize(sendPayload); 
       sendpckt->printContents(); 
       sendPacket = sendto(sendSocket, sendPayload, sizeof(sendPayload), 0, (struct sockaddr *)&sendSocketStruct, sendSocketLen); 
      } 

      sendFlag = 0; 
      previousState = currentState; 
      currentState = wait; 
     } 
     else if (currentState == receiveData) 
     { 
      bzero(receivePayload, 1024); 
      receive = (recvfrom(receiveSocket, receivePayload, sizeof(receivePayload), 0, (struct sockaddr *)&receiveSocketStruct, &receiveSocketLen)); 
      if (errno == EINTR) 
      { 
       printf("timeout"); 
       if (tries > MAXTRIES) 
       { 
        alarm(0); 
        break; 
        printf("recvfrom() failed."); 
       } 

       previousState = currentState; 
       currentState = timeout; 
      } 
      else 
      { 
       char buffer[1024]; 
       bzero(buffer, 1024); 
       int receivePacketType; 
       int receivePacketSeqNum; 

       packet recvpckt(0, 0, 0, (char*)buffer); 
       recvpckt.deserialize((char*)receivePayload); 

       receivePacketSeqNum = recvpckt.getSeqNum(); 
       receivePacketType = recvpckt.getType(); 
       recvpckt.printContents(); 

       if (receivePacketType == 2) 
       { 
        break; 
       } 

       base = receivePacketSeqNum + 1; 
       printf("%d\n", base); 

       if (base == nextSeqNum) 
       { 
        alarm(0); 
       } 
       else 
       { 
        alarm(0); 
        alarm(TIMEOUT_SECS); 
       } 

       if (nextSeqNum == totalPackets - 1) 
       { 
        nextSeqNum++; 
        int sendPacket = 0; 
        bzero(sendPayload, 1024); 
        packet * sendpckt = packetArray[nextSeqNum - 1]; 
        sendpckt->serialize(sendPayload); 
        sendpckt->printContents(); 
        sendPacket = sendto(sendSocket, sendPayload, sizeof(sendPayload), 0, (struct sockaddr *)&sendSocketStruct, sendSocketLen); 
       } 

       if (base <= totalPackets) 
       { 
        sendFlag = 1; 
        previousState = currentState; 
        currentState = wait; 
       } 
       else 
       { 
        continue; 
       } 
      } 
     } 
     else 
     { 
      break; 
     } 
    } 

    //Close shop. 
    close(receiveSocket); 
    close(sendSocket); 

    return 0; 
} 

루프가 시작될 것으로 의심되는 위치는 receiveData 상태입니다.

답변

0

그것을 고정 :

else if (currentState == receiveData) 
     { 
      receive = 0; 
      bzero(receivePayload, 1024); 
      receive = (recvfrom(receiveSocket, receivePayload, sizeof(receivePayload), 0, (struct sockaddr *)&receiveSocketStruct, &receiveSocketLen)); 
      if (receive < 0) 
      { 
       printf("timeout"); 
       if (tries > MAXTRIES) 
       { 
        alarm(0); 
        break; 
        printf("recvfrom() failed."); 
       } 

      previousState = currentState; 
      currentState = timeout; 
     }