Я пытаюсь реализовать протокол GoBackN, и когда сервер отбрасывает пакет, мой сигнал тревоги ждет 2 секунды, прежде чем отправлять все ранее отправленные пакеты.
Тревога срабатывает и ждет 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
государство.
Починил это:
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;
}
Других решений пока нет …