Here it is the simplePing, it is a simple multithreaded ping implementation coded from scratch.
First of all we need some requirements to satisfy:
REQ_OS_01
simplePing shall run on Linux Systems.
REQ_OS_03
simplePing shall be invoked using the shell an it shall receive (from the shell) the following arguments:
1. The destination IP address
2. An optional flag to setup the verbose mode
REQ_OS_04
simplePing shall use the standard posix threads to implement:
a. the pinger part
b. the listener part.
REQ_OS_05
simplePing shall return EXIT_FAILURE in case of failure or EXIT_SUCCESS in case of success (when the user hits CTRL-C).
REQ_COM_02
simplePing shall use the standard ICMP protocol.
REQ_COM_03
simplePing shall send an ECHO request every seconds.
REQ_COM_04
The ECHO request shall be non blocking.
Just a little code…
int main(int argc, char **argv) /* REQ_OS_03 CLI arguments. */
{
…….
…….
/* Trapping the CTRL-C */
signal(SIGINT, quitProgram);
if ((argc<2)||(argc>3)) /* REQ_OS_03 CLI arguments. */
Usage(argv);
…….
…….
/* REQ_OS_04.a */
/* Create the listener thread */
pthread_create(&listenerThreadId, NULL, listener, NULL);
sleep(1);
/* REQ_OS_04.b */
/* Create the pinger thread */
pthread_create(&pingerThreadId, NULL, ping, addr);
/* Wait for the end of both threads. */
pthread_join(pingerThreadId, NULL);
pthread_join(listenerThreadId, NULL);
…….
}
/*+——————————————————+
| Function name : listener |
+——————————————————+*/
void *listener(void *par)
{
…….
/* using the IGMP protocol */
sd = socket(PF_INET, SOCK_RAW, globalData.protocol->p_proto);
…….
while(!donel)
{
…….
/* waiting for data */
if (bytes > 0)
printInfo(buf, bytes);
…….
…….
return(NULL);
}
/*+——————————————————+
| Function name : ping |
| Parameters : |
| in : The destination IP address. |
| Return value : NULL or EXIT_FAILURE. |
| Description : The pinger function. |
+——————————————————+*/
void *ping(void *par)
{
…….
/* using the IGMP protocol */
sd = socket(PF_INET, SOCK_RAW, globalData.protocol->p_proto);
…….
/* Setting TTL to 255*/
if (setsockopt(sd, SOL_IP, IP_TTL, &val, sizeof(val)) != 0)
{
perror("Set TTL option");
exit(EXIT_FAILURE);
}
/* Requesting non blocking I/O */
if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0)
{
perror("Request nonblocking I/O");
exit(EXIT_FAILURE);
}
while(!done)
{
…….
/* Sending one message per second until CTRL-C will be pushed and then "done"==true */
/* Preparing the packet to send */
pckt.hdr.type = ICMP_ECHO;
pckt.hdr.un.echo.id = globalData.pid;
for (i = 0; i < sizeof(pckt.msg)-1; i++)
pckt.msg[i] = i+'0';
pckt.msg[i] = 0;
pckt.hdr.un.echo.sequence = packetsSent++;
pckt.hdr.checksum = checksum(&pckt, sizeof(pckt));
/* Sending the packet */
{
perror("sendto");
}
sleep(1);
}
return(NULL);
}
You can download the simplePing here. simplePing
To compile simplePing just run the "make" command.
To run simplePing you must be root.
Gg1
The link with simplePing.zip is not working. I was kind of hoping to revise the code.
@S_i_g_n_e_D Thank you for reporting the non working link.
Now it should work fine.
Quite a fast response 😉 Thank you. By the way I'll implement Emery Berger's dthreads … just for the sport 😉 It's interesting for me to measure the performance of both implementations because of a future project decision.
Emery Berger’s dthreads? Interesting! Please let me know if you will post your results. Good Luck!
That was enjoyable to read, thanks for posting it.