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

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. python中的argparse

    argparse是python用于解析命令行参数和选项的标准模块,用于代替已经过时的optparse模块.argparse模块的作用是用于解析命令行参数. 最基础的,从一个最简单的程序开始: impo ...

  2. go语言 类型:数组切片

    初看起来,数组切片就像一个指向数组的指针,实际上它拥有自己的数据结构,而不仅仅是个指针.数组切片的数据结构可以抽象为以下3个变量: 1.一个指向原生数组的指针: 2.数组切片中的元素个数: 3.数组切 ...

  3. 2016年末闲谈iOS开发的未来

    移动开发市场潮流涌动,好多人都会问iOS开发的前景这样的问题,今天我就瞎扯一下我眼中的未来,纯主观非理性,爱看看. Swift怎么样 Swift很好,就像你的前女友一样好. 得益于swift的开源,以 ...

  4. jQuery.extend()方法和jQuery.fn.extend()方法源码分析

    这两个方法用的是相同的代码,一个用于给jQuery对象或者普通对象合并属性和方法一个是针对jQuery对象的实例,对于基本用法举几个例子: html代码如下: <!doctype html> ...

  5. 在线代码编辑器CodeMirror简介

    1.什么是Code Mirror 最近做一个项目需要在网页上实现一个代码编辑器,支持语法高亮.自动缩进.智能提示等功能.发现Code Mirror刚好满足所有需求.Code Mirror是由js写的一 ...

  6. MS15-020漏洞测试

    名称:Microsoft DLL植入远程代码执行漏洞(CVE-2015-0096)(MS15-020) 了解:Microsoft Windows没有正确处理DLL文件的加载,存在远程代码执行漏洞,通过 ...

  7. 约瑟夫环问题分析-C语言经典面试题

    好久没有看有关算法的问题了,今天废了不少劲,再感叹一句:要想学好算法就要常练习,没什么捷径可走.废话不多说,如下: 问题描述:有m个人,围成一个环,编号为 0.1.2.3...m-1,从第一个人开始循 ...

  8. iOS事件响应链

    首先,当发生事件响应时,必须知道由谁来响应事件.在IOS中,由响应者链来对事件进行响应,所有事件响应的类都是UIResponder的子类,响应者链是一个由不同对象组成的层次结构,其中的每个对象将依次获 ...

  9. redis如何执行redis命令

    Redis 命令 Redis 命令用于在 redis 服务上执行操作.所以我们必须要启动Redis服务程序,也就是redis安装目录下的redis-server.exe,你可以双击执行,也可以打开cm ...

  10. CSS行高——line-height

    学习资料 : http://www.cnblogs.com/dolphinX/p/3236686.html