Ping程序示例

来源:互联网 发布:离散最优化算法 编辑:程序博客网 时间:2024/06/04 00:45
#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <stdint.h>#include <stdbool.h>#include <libgen.h>#include <sys/types.h>#include <sys/time.h>#include <signal.h>#include <unistd.h>#include <fcntl.h>#include <arpa/inet.h>#include <netinet/ip_icmp.h>#ifndef likely#define likely(x) __builtin_expect(!!(x), 1)#endif#ifndef unlikely#define unlikely(x) __builtin_expect(!!(x), 0)#endif#define PACKETSIZE  64struct packet_st{struct icmphdr icmph;char message[PACKETSIZE-sizeof(struct icmphdr)];};static volatile sig_atomic_t isterm = 0;   // 结束信号static volatile sig_atomic_t isalarm = 0;  // 时钟信号(1秒1次)// 中断后的信号处理函数static void signals_handler(int sig, siginfo_t *si, void *context){switch(sig){case SIGINT: case SIGTERM:isterm = sig;break;case SIGALRM: isalarm = sig;break;default:break;}}// 注册信号中断static void signals_register(){struct sigaction act;struct itimerval interval;sigfillset(&act.sa_mask);sigdelset(&act.sa_mask, SIGINT);sigdelset(&act.sa_mask, SIGTERM);sigdelset(&act.sa_mask, SIGALRM);sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);act.sa_flags = SA_SIGINFO;act.sa_sigaction = signals_handler;interval.it_interval.tv_sec = 1;interval.it_interval.tv_usec = 0;interval.it_value.tv_sec = 1;interval.it_value.tv_usec = 0;sigaction(SIGINT, &act, NULL);sigaction(SIGTERM, &act, NULL);sigaction(SIGALRM, &act, NULL);setitimer(ITIMER_REAL, &interval, NULL);}/* * in_cksum -- *      Checksum routine for Internet Protocol family headers (C Version) */unsigned short in_cksum(unsigned short *addr,int len){register int sum = 0;unsigned short answer = 0;register unsigned short *w = addr;register int nleft = len;/* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */while (nleft > 1)  {sum += *w++;nleft -= 2;}/* mop up an odd byte, if necessary */if (nleft == 1) {*(unsigned char *)(&answer) = *(unsigned char *)w ;sum += answer;}/* add back carry outs from top 16 bits to low 16 bits */sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */sum += (sum >> 16);                     /* add carry */answer = ~sum;                          /* truncate to 16 bits */return(answer);}int pinger(char *ip){int fd = 0;    static unsigned short count = 0;fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);if(fd == -1){fprintf(stderr, "socket(): %s\n", strerror(errno));return -1;}fcntl(fd, F_SETFD, FD_CLOEXEC);fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);int flag = 1;struct timeval tv = {.tv_sec = 3,.tv_usec = 0};setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(int));setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval));setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));struct packet_st pkt;memset(&pkt, 0, sizeof(struct packet_st));pkt.icmph.type = ICMP_ECHO;pkt.icmph.code = 0;pkt.icmph.un.echo.id = (unsigned short)getpid();pkt.icmph.un.echo.sequence = ++count;pkt.icmph.checksum = in_cksum((unsigned short*)&pkt, sizeof(struct packet_st));struct sockaddr_in addr, from;memset(&addr, 0, sizeof(struct sockaddr_in));memset(&from, 0, sizeof(struct sockaddr_in));addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr(ip);        int ret = 0;    socklen_t len = sizeof(struct sockaddr);ret = sendto(fd, &pkt, sizeof(struct packet_st), 0, (struct sockaddr*)&addr, len);if(ret == -1 && errno != EINTR){fprintf(stderr, "sendto(): %s\n", strerror(errno));goto EndP;}fprintf(stdout, "sendto: %s\n", ip);fd_set readfds;FD_ZERO(&readfds);FD_SET(fd, &readfds);while((ret = select(fd+1, &readfds, NULL, NULL, &tv))){if(ret == -1 && errno != EINTR){fprintf(stderr, "select(): %s\n", strerror(errno));continue;}if(0 <= fd && fd < FD_SETSIZE && FD_ISSET(fd, &readfds)){ret = recvfrom(fd, &pkt, sizeof(struct packet_st), 0, (struct sockaddr*)&from, &len);if(ret == -1 && errno != EINTR){fprintf(stderr, "recvfrom(): %s\n", strerror(errno));continue;}fprintf(stdout, "recvfrom: %s\n", inet_ntoa(from.sin_addr));break;}}FD_CLR(fd, &readfds);EndP:if(fd) close(fd);return ret;}int main(int argc, char *argv[]){if(argc != 2){fprintf(stderr, "Usage: %s IPADDR\n", argv[0]);return -1;}signals_register();while(!isterm){if(unlikely(isterm)){fprintf(stdout, "term signal: %d\n", isterm);isterm = 0;}if(likely(isalarm)){fprintf(stdout, "alarm signal: %d\n", isalarm);isalarm = 0;pinger(argv[1] ? argv[1] : "127.0.0.1");}sleep(-1);}return 0;}

0 0