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

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. Java经典实例:使用ChoiceFormat来格式化复数

    import java.text.ChoiceFormat; /** * Created by Frank */ public class FormatPuralsChoice extends For ...

  2. Java继承和接口

    接口最关键的作用,也是使用接口最重要的一个原因:能上溯造型至多个基础类.使用接口的第二个原因与使用抽象基础类的原因是一样的:防止客户程序员制作这个类的一个对象,以及规定它仅仅是一个接口.这样便带来了一 ...

  3. 哇 真的是一个好插件!!!Sublime Text编辑文件后快速刷新浏览器

    http://9iphp.com/web/html/sublime-text-refresh-browser.html这篇博文咯 来源:[Tips]Sublime Text编辑文件后快速刷新浏览器 - ...

  4. 使用 jQuery Mockjax 插件模拟 Ajax 请求

    在实际的开发过程中,前端后台协商好了统一的接口,就各自开始自己的任务了.这时候我有这么一个 Ajax 请求需要从后台获取数据: $.ajax({ url: '/products/' }).done(f ...

  5. SharePoint 2013 和卷影复制服务(VSS)概述

    对备份供应商而言,卷影复制服务 (VSS) 使用集中式 API 简化了 Microsoft 服务器解决方案的备份.Microsoft SharePoint Foundation 包括一个参考 VSS ...

  6. Android使用Fragment来实现TabHost的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信

    以下内容为原创,转载请注明:http://www.cnblogs.com/tiantianbyconan/p/3360938.html 如新浪微博下面的标签切换功能,我以前也写过一篇博文(http:/ ...

  7. 配置redis外网可访问,并只允许指定的ip可访问redis

    开启redis 允许外网IP 访问 在 Linux 中安装了redis 服务,当在客户端通过远程连接的方式连接时,报could not connect错误. 错误的原因很简单,就是没有连接上redis ...

  8. 操作系统开发系列—11.ELF格式 ●

    ELF文件的结构如下图所示: ELF文件由4部分组成,分别是ELF头(ELF header).程序头表(Program header table).节(Sections)和节头表(Section he ...

  9. <转>最新版SDWebImage的使用

    我之前写过一篇博客,介绍缓存处理的三种方式,其中最难,最麻烦,最占内存资源的还是图片缓存,最近做的项目有大量的图片处理,还是采用了SDWebImage来处理,但是发现之前封装好的代码报错了.研究发现, ...

  10. 5个强大的Java分布式缓存框架推荐

    在开发中大型Java软件项目时,很多Java架构师都会遇到数据库读写瓶颈,如果你在系统架构时并没有将缓存策略考虑进去,或者并没有选择更优的 缓存策略,那么到时候重构起来将会是一个噩梦.本文主要是分享了 ...