#include /* for printf() and fprintf() */ #include /* for socket(), connect(), sendto(), and recvfrom() */ #include /* for sockaddr_in and inet_addr() */ #include /* for atoi() and exit() */ #include /* for memset() */ #include /* for close() */ #include /* for errno and EINTR */ #include /* for sigaction() */ #define ECHOMAX 255 /* Longest string to echo */ #define TIMEOUT_SECS 2 /* Seconds between retransmits */ #define MAXTRIES 5 /* Tries before giving up */ int tries=0; /* Count of times sent - GLOBAL for signal-handler access */ void DieWithError(char *errorMessage); /* Error handling function */ void CatchAlarm(int ignored); /* Handler for SIGALRM */ int main(int argc, char *argv[]) { int sock; /* Socket descriptor */ struct sockaddr_in echoServAddr; /* Echo server address */ struct sockaddr_in fromAddr; /* Source address of echo */ unsigned short echoServPort; /* Echo server port */ unsigned int fromSize; /* In-out of address size for recvfrom() */ struct sigaction myAction; /* For setting signal handler */ char *servIP; /* IP address of server */ char *echoString; /* String to send to echo server */ char echoBuffer[ECHOMAX+1]; /* Buffer for echo string */ int echoStringLen; /* Length of string to echo */ int respStringLen; /* Size of received datagram */ if ((argc < 3) || (argc > 4)) /* Test for correct number of arguments */ { fprintf(stderr,"Usage: %s []\n", argv[0]); exit(1); } servIP = argv[1]; /* First arg: server IP address (dotted quad) */ echoString = argv[2]; /* Second arg: string to echo */ if ((echoStringLen = strlen(echoString)) > ECHOMAX) DieWithError("Echo word too long"); if (argc == 4) echoServPort = atoi(argv[3]); /* Use given port, if any */ else echoServPort = 7; /* 7 is well-known port for echo service */ /* Create a best-effort datagram socket using UDP */ if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) DieWithError("socket() failed"); /* Set signal handler for alarm signal */ myAction.sa_handler = CatchAlarm; if (sigfillset(&myAction.sa_mask) < 0) /* block everything in handler */ DieWithError("sigfillset() failed"); myAction.sa_flags = 0; if (sigaction(SIGALRM, &myAction, 0) < 0) DieWithError("sigaction() failed for SIGALRM"); /* Construct the server address structure */ memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */ echoServAddr.sin_family = AF_INET; echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */ echoServAddr.sin_port = htons(echoServPort); /* Server port */ /* Send the string to the server */ if (sendto(sock, echoString, echoStringLen, 0, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) != echoStringLen) DieWithError("sendto() sent a different number of bytes than expected"); /* Get a response */ fromSize = sizeof(fromAddr); alarm(TIMEOUT_SECS); /* Set the timeout */ while ((respStringLen = recvfrom(sock, echoBuffer, ECHOMAX, 0, (struct sockaddr *) &fromAddr, &fromSize)) < 0) if (errno == EINTR) /* Alarm went off */ { if (tries < MAXTRIES) /* incremented by signal handler */ { printf("timed out, %d more tries...\n", MAXTRIES-tries); if (sendto(sock, echoString, echoStringLen, 0, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) != echoStringLen) DieWithError("sendto() failed"); alarm(TIMEOUT_SECS); } else DieWithError("No Response"); } else DieWithError("recvfrom() failed"); /* recvfrom() got something -- cancel the timeout */ alarm(0); /* null-terminate the received data */ echoBuffer[respStringLen] = '\0'; printf("Received: %s\n", echoBuffer); /* Print the received data */ close(sock); exit(0); } void CatchAlarm(int ignored) /* Handler for SIGALRM */ { tries += 1; }