写这个的目的主要是为了以后的方便:

1.信号计时函数的使用

2.ip头的构建和icmp头的构建

3.selec函数t的用法

代码实现:

/src/ping.h

 /*
* ping.h
*
* Created on: 2015年11月6日
* Author: root
*/ #ifndef PING_H_
#define PING_H_ #endif /* PING_H_ */ #include <sys/types.h>
#include <sys/select.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/ip_icmp.h>
#include<errno.h> /*sys/types.h中文名称为基本系统数据类型*/ #define N 200005
#define PACKET_SIZE 1024*4 extern FILE *out;
extern int nsent;
extern int nrecv; extern char * intip_to_ipv4(unsigned int ip);
extern void recv_all_packet(int sockfd);
extern int send_one_packet(int sockfd, unsigned int ip_num, int pid);

/src/ping.h

/src/ping_project.c

 /*
============================================================================
Name : ping_project.c
Author : huh
Version :
Copyright : ---notice---
Description : Hello World in C, Ansi-style
============================================================================
*/ #include "ping.h" FILE *out; int pid;
int the_number_of_ping = ;
int send_sockfd, recv_sockfd;
int ping_num = ; //ip地址数量
unsigned int addr[N]; //ip地址数组
struct sigaction act_alarm;
struct timeval timeout;
struct itimerval val_alarm ={
.it_interval.tv_sec = ,
.it_interval.tv_usec = ,
.it_value.tv_sec = ,
.it_value.tv_usec = };
fd_set init_recv_sockets, recv_sockets;
fd_set init_send_sockets, send_sockets, init_send_sockets_2; int size = * ; void init_ip();
void sig_alrm(int singo); int main(void)
{
init_ip();
out = fopen("./src/file/a.out", "w");
if (out == NULL)
{
perror("stdout error!\n");
}
int flag1, flag2;
pid = getpid();
send_sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
//if(send_sockfd < 0) { perror("send_sockfd error:"); return 0; }
flag1 = setsockopt(send_sockfd, IPPROTO_IP, IP_HDRINCL, &size,
sizeof(size));
//if(flag1<0) { perror("setsockopt error:"); return 0; }
recv_sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
//if(recv_sockfd < 0) { perror("recv_sockfd error:"); return 0; }
flag2 = setsockopt(recv_sockfd, IPPROTO_IP, IP_HDRINCL, &size,
sizeof(size));
//if(flag2<0) { perror("setsockopt error:"); return 0; } act_alarm.sa_handler = sig_alrm;
if (sigaction(SIGALRM, &act_alarm, NULL) == -)
printf("SIGALRM handler setting fails.\n"); if ((setitimer(ITIMER_REAL, &val_alarm, NULL)) == -) /*定时函数*/
printf("setitimer fails.\n"); int result;
int maxfdp1;
int k = ; FD_ZERO(&init_recv_sockets);
FD_SET(recv_sockfd, &init_recv_sockets); FD_ZERO(&init_send_sockets);
FD_SET(send_sockfd, &init_send_sockets);
init_send_sockets_2 = init_send_sockets; maxfdp1 = recv_sockfd + ;
while () //无限循环,接受包
{
recv_sockets = init_recv_sockets;
send_sockets = init_send_sockets_2;
timeout.tv_sec = ;
timeout.tv_usec = ;
result = select(maxfdp1, &recv_sockets, &send_sockets, NULL, &timeout);
switch (result)
{
case :
printf("共发送了%d个包, 收到了%d个包\n", nsent, nrecv);
printf("timeout:程序结束!\n");
return ;
break;
case -:
if (errno == EINTR)
continue;
perror("select:");
return ;
break;
default:
if (FD_ISSET(recv_sockfd, &recv_sockets))
recv_all_packet(recv_sockfd);
if (FD_ISSET(send_sockfd, &send_sockets))
{
send_one_packet(send_sockfd, addr[k], pid);
k = (k + ) % ping_num;
if (k == )
FD_ZERO(&init_send_sockets_2);
}
break;
}
}
return ;
} void sig_alrm(int singo)
{
the_number_of_ping++;
if (the_number_of_ping <= )
{
printf("ping了第%d遍!\n", the_number_of_ping);
init_send_sockets_2 = init_send_sockets;
} else
{
val_alarm.it_interval.tv_sec = ;
val_alarm.it_interval.tv_usec = ;
val_alarm.it_value = val_alarm.it_interval;
setitimer(ITIMER_REAL, &val_alarm, NULL);
}
} void init_ip() //将要访问的主机全部变成32位无符号的ip。
{
FILE *in;
unsigned int name;
char str[];
struct hostent *host; in = freopen("./src/file/a.in", "r", stdin);
if (in == NULL)
{
printf("stdin error!\n");
} while (!feof(in))
{
scanf("%s", str); //ip地址或域名
name = inet_addr(str); //将一个点分十进制IP转化为长整数
if (name == INADDR_NONE)
{
host = gethostbyname(str);
if (host == NULL)
{
printf("参数格式不正确,请重新输入!\n");
continue;
}
memcpy((char*) &name, host->h_addr, );
}
addr[ping_num] = name;
printf("%s:%s\n", str, intip_to_ipv4(name));
ping_num++;
}
printf("程序将 ping %d 个IP.\n", ping_num);
}

/src/ping_project.c

/src/send.c

 /*
* send.c
*
* Created on: 2015年11月6日
* Author: root
*/ #include "ping.h" int icmp_len;
int flag;
int nsent=;
int datalen = ;
struct icmp *icmp;
char sendbuf[PACKET_SIZE];
struct sockaddr_in dest_addr; //socket目的地址 unsigned short cal_chksum(unsigned short *addr, int len)
{
int nleft = len;
int sum = ;
unsigned short *w = addr;
unsigned short answer = ;
//把ICMP报头二进制数据以2字节为单位累加起来
while (nleft > )
{
sum += *w++;
nleft -= ;
}
if (nleft == )
{
*(unsigned char *)(&answer) = *(unsigned char *)w;
sum += answer;
}
sum = (sum>>) + (sum&0xffff);
sum += (sum>>);
answer = ~sum;
return answer;
} char * intip_to_ipv4(unsigned int ip)
{
char *str;
struct in_addr des;
des.s_addr = ip;
str = inet_ntoa(des);
//printf("---%s---\n",str);
return str;
} int send_one_packet(int sockfd, unsigned int ip_num, int pid)
{
struct iphdr *ip;
ip = (struct iphdr *)sendbuf;
ip->ihl = sizeof(struct iphdr) >> ; //首部长度
ip->version = ; //ip协议版本
ip->tos = ; //服务类型字段
ip->tot_len = ; //总长度
ip->id = ;
ip->frag_off = ;
ip->ttl = ;
ip->protocol = IPPROTO_ICMP;
ip->check = ; //让内核算 dest_addr.sin_family = AF_INET;
memcpy((char *)&dest_addr.sin_addr, (char *)&ip_num,sizeof(ip_num));
//ip->saddr = src_addr.sin_addr.s_addr;
ip->daddr = dest_addr.sin_addr.s_addr; icmp = (struct icmp *)(sendbuf + sizeof(struct iphdr));
icmp->icmp_type = ICMP_ECHO; //拼接icmp
icmp->icmp_code = ;
icmp->icmp_id = pid; //2字节
icmp->icmp_seq = ++nsent; //2字节
memset(icmp->icmp_data, 0xa5, datalen);
gettimeofday((struct timeval *)icmp->icmp_data, NULL); //将发送时间作为数据传递过去 icmp_len = datalen + ;
icmp->icmp_cksum = ;
icmp->icmp_cksum = cal_chksum((unsigned short *)icmp, icmp_len); flag = sendto(sockfd, sendbuf, ip->tot_len, , (struct sockaddr *)&dest_addr, sizeof(dest_addr)); //将包发出去
//if(flag < 0) { printf("sendto error!\n"); return 0; } fprintf(out,"inet addr:%s 's packet have sent!\n",intip_to_ipv4(ip_num));
return ;
}

/src/send.c

/src/recv.c

 /*
* recv.c
*
* Created on: 2015年11月6日
* Author: root
*/ #include "ping.h" int nrecv=;
struct timeval tvrecv;
char recvbuf[PACKET_SIZE];
struct sockaddr_in src_addr; //socket源地址 int len; //统计收到的包的长度
int src_addr_len = sizeof(struct sockaddr_in); void tv_sub(struct timeval *out,struct timeval *in)
{
if ((out->tv_usec-=in->tv_usec) < )
{
--out->tv_sec;
out->tv_usec += ;
}
out->tv_sec -= in->tv_sec;
} void unpacket(int sockfd, int len,int pid)
{
//int len;
double rtt;
int iphdrlen;
struct ip *ip;
struct icmp *icmp;
struct timeval *tvsend; gettimeofday(&tvrecv,NULL);
ip = (struct ip *)recvbuf;
iphdrlen = ip->ip_hl<<;
//printf("%d\n",iphdrlen);
icmp = (struct icmp *)(recvbuf+iphdrlen);
len -= iphdrlen; if((icmp->icmp_type == ICMP_ECHOREPLY) && (icmp->icmp_id == pid))
{
tvsend = (struct timeval *)icmp->icmp_data;
tv_sub(&tvrecv, tvsend);//接收和发送的时间差
rtt = tvrecv.tv_sec*1000.0 + (1.0*tvrecv.tv_usec)*0.001;//以毫秒单位计算rtt
fprintf(out,"%d byte from %s: icmp_seq=%u ttl=%d rtt=%.3f ms\n", len, inet_ntoa(ip->ip_src), icmp->icmp_seq, ip->ip_ttl, rtt);
nrecv++;
}
//sleep(1);
} void recv_all_packet(int recv_sockfd)
{
len = recvfrom(recv_sockfd, recvbuf, sizeof(recvbuf), , (struct sockaddr *)&src_addr, (socklen_t *)&src_addr_len);
if(len < )
perror("recvfrom:");
unpacket(recv_sockfd, len, getpid());
return ;
}

/src/recv.c

/src/file/a.in

 www.baidu.com
www.qq.com
www.jd.com
www.aminglinux.com
map.baidu.com
music.baidu.com
image.baidu.com
zhidao.baidu.com
www.tmall.com
127.0.0.1

/src/file/a.in

003.同时Ping多个IP(select实现IO复用,信号计时),ping程序升级版的更多相关文章

  1. python实现本地批量ping多个IP

    本文主要利用python的相关模块进行批量ping ,测试IP连通性. 下面看具体代码(python3): #!/usr/bin/env python#-*-coding:utf-8-*- impor ...

  2. linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)

      IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file ...

  3. 使用select io复用实现超时设置

    在linux的socket编程中,经常会遇到超时设置的问题,例如请求方如果在Ks内不发送数据则服务器要断开连接停止服务.这里我使用select的io复用实现超时5s设置,具体代码片段如下: fd_se ...

  4. 在windows命令行批量ping局域网内IP

    参考了博客园Alfred Zhao的文章<Windows平台ping测试局域网所有在用IP> 在cmd命令行运行如下命令即可: ,,) -w .%i | find "回复&quo ...

  5. Windows 局域网ping获取设备IP

    /********************************************************************** * Windows 局域网ping获取设备IP * 说明 ...

  6. Linux下批量ping某个网段ip的脚本

    比如现在需要对172.16.50.0/24网段的ip进行检查,检查哪些ip现在被占用,哪些ip没有被占用,可以通过ping命令来检查,脚本如下: [root@uatdns01 opt]# vim /o ...

  7. windows与linux ping 显示的ip不一样

    DNS修改了一下域名对应的IP后,域名不能访问了,我在windows下ping一下域名,IP没有变过来,还是老的IP.我在linux下又ping了一下域名,是换过了的.这个问题是由windows下的本 ...

  8. Qt5.2中使用ping命令实现Ip扫描功能

    在实现类似于Free IP Scanner 2.1的Ip扫描器软件中,会用到ping命令.如果使用Qt编程实现,主要会用QThread.QProcess这两个类.关于这两个类的具体用法可以查阅Qt助手 ...

  9. VMware_win10能ping通虚拟机ip,虚拟机ping不通win10ip的解决方法

    一.虚拟机设置为桥接模式 二.修改虚拟机linux的ip 查看win10的ip和网关 使用ifconfig查看网卡名,并在 /etc/sysconfig/network-scripts/目录修改对应的 ...

随机推荐

  1. 【FOL】第三周

    这周还是在改自己的这个框架,被多线程折腾了两天,最终无奈放弃在游戏启动时调用引擎进行图片相关资源的初始化,当然进展还是不错的. 嗯,下面还是以流水的方式继续记录一下本周完成的工作: 1.调通了客户端与 ...

  2. CodeBlock

    CodeBlock官网是: http://www.codeblocks.org/ 选择Download the binary release: 根据自己电脑的情况选择想要的版本:(以博主电脑为例,wi ...

  3. Webform(分页与组合查询配合使用)

    1.封装实体类 2.写查询方法 //SubjectData类 public List<Subject> Select(string name) { List<Subject> ...

  4. 01Mybatis_课程安排

    课程安排: mybatis和springmvc通过订单商品 案例驱动 第一天:基础知识(重点,内容量多) 对原生态jdbc程序(单独使用jdbc开发)问题总结 mybatis框架原理   (掌握) m ...

  5. 《Continuous Delivery》 Notes 1: The problem of delivering software

    What is "Deployment pipeline"? A deployment pipeline is an automated implementation of you ...

  6. MixItUp:超炫!基于 CSS3 & jQuery 的过滤和排序插件

    MixItUp 是一款轻量,但功能强大的 jQuery 插件,提供了对分类和有序内容的美丽的动画过滤和排序功能.特别适合用于作品集网站,画廊,图片博客以及任何的分类或有序内容. 它是如何工作的? Mi ...

  7. 学习 Mobile App 网站制作的11个优秀案例

    我喜欢收集美丽的,精心设计的移动应用程序网站.在我看来,为 App 提供一个美丽的网站显示了设计者和开发者对它的用户和产品的关心,除了开发应用程序,他们去加倍努力去促进应用和传播关于它的 App. 我 ...

  8. 【初探移动前端开发03】jQuery Mobile(上)

    前言 到目前为止,我打了几天酱油了,这几天落实了工作,并且看了一部电视连续剧(陈道明-手机),我很少看连续剧了,但是手机质量很高啊,各位可以看看. 我们今天先学习一下jquery mobile的基础知 ...

  9. Android压力测试工具——Monkey

    Android压力测试工具——Monkey Monkey是运行在模拟器上和真机设备上的一段程序,它会产生用户事件的一系列伪随机流,比如点击.触摸.手势,还有很多系统级别的事件.Monkey通常是用来做 ...

  10. 关于OC中的block自己的一些理解(一)

    一.关于block 1.block的作用:保存一段代码. 2.苹果官方推荐的一种语法,类似于C语言的函数,但是比函数更加灵活. 3.^是block语法的标识. 二.block的用法 1)无返回值无参数 ...