linux:C语言通过ICMP协议判断局域网内部主机是否存活
ICMP协议
ICMP(Internet Control Message,网际控制报文协议)是为网关和目标主机而提供的一种差错控制机制,使它们在遇到差错时能把错误报告给报文源发方。
ICMP协议是IP层的一个协议,但是由于差错报告在发送给报文源发方时可能也要经过若干子网,因此牵涉到路由选择等问题,所以ICMP报文需通过IP协议来发送。
ICMP数据报的数据发送前需要两级封装:首先添加ICMP报头形成ICMP报文,再添加IP报头形成IP数据报。
main.cpp :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <signal.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <setjmp.h>
#include <errno.h>
#include <sys/select.h>
#include <fcntl.h>
#define PACKET_SIZE 4096
/* 计算校验和的算法 */
unsigned short cal_chksum(unsigned short *addr,int len)
{
int sum=;
int nleft = len;
unsigned short *w = addr;
unsigned short answer = ;
/* 把ICMP报头二进制数据以2字节为单位累加起来 */
while(nleft > ){
sum += *w++;
nleft -= ;
}
/*
* 若ICMP报头为奇数个字节,会剩下最后一字节。
* 把最后一个字节视为一个2字节数据的高字节,
* 这2字节数据的低字节为0,继续累加
*/
if(nleft == ){
*(unsigned char *)(&answer) = *(unsigned char *)w;
sum += answer; /* 这里将 answer 转换成 int 整数 */
}
sum = (sum >> ) + (sum & 0xffff); /* 高位低位相加 */
sum += (sum >> ); /* 上一步溢出时,将溢出位也加到sum中 */
answer = ~sum; /* 注意类型转换,现在的校验和为16位 */
return answer;
}
int livetest(char* ip) { char sendpacket[PACKET_SIZE]; /* 发送的数据包 */
char recvpacket[PACKET_SIZE]; /* 接收的数据包 */
pid_t pid;
int datalen = ; /* icmp数据包中数据的长度 */
struct protoent *protocol;
protocol = getprotobyname("icmp");
int sockfd;
int size = *;
if((sockfd = socket(AF_INET, SOCK_RAW, protocol->p_proto)) < ) {
perror("socket error");
}
setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size) ); struct sockaddr_in dest_addr;
bzero(&dest_addr, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
dest_addr.sin_addr.s_addr = inet_addr(ip);
//send packet;
int packsize;
struct icmp *icmp;
struct timeval *tval;
icmp = (struct icmp*)sendpacket;
icmp->icmp_type = ICMP_ECHO; /* icmp的类型 */
icmp->icmp_code = ; /* icmp的编码 */
icmp->icmp_cksum = ; /* icmp的校验和 */
icmp->icmp_seq = ; /* icmp的顺序号 */
icmp->icmp_id = pid; /* icmp的标志符 */
packsize = + datalen; /* icmp8字节的头 加上数据的长度(datalen=56), packsize = 64 */
tval = (struct timeval *)icmp->icmp_data; /* 获得icmp结构中最后的数据部分的指针 */
gettimeofday(tval, NULL); /* 将发送的时间填入icmp结构中最后的数据部分 */
icmp->icmp_cksum = cal_chksum((unsigned short *)icmp, packsize);/*填充发送方的校验和*/ if(sendto(sockfd, sendpacket, packsize, , (struct sockaddr *)&dest_addr, sizeof(dest_addr)) < ){
perror("sendto error");
}
printf("send %d, send done\n", );
int n;
struct sockaddr_in from;
int fromlen = sizeof(from);
fcntl(sockfd, F_SETFL, O_NONBLOCK);
struct timeval timeo = {,};
fd_set set;
FD_ZERO(&set);
FD_SET(sockfd, &set);
//read , write;
int retval = select(sockfd+, &set, NULL, NULL, &timeo);
if(retval == -) {
printf("select error\n");
return ;
}else if(retval == ) {
printf("timeout\n");
return ;
}else{
if( FD_ISSET(sockfd, &set) ){
printf("host is live\n");
return ;
}
}
// n = recvfrom(sockfd, recvpacket,sizeof(recvpacket), 0, (struct sockaddr *)&from, (socklen_t *)&fromlen);
// if(n<0) {
// perror("recvfrom error");
// }else{
// printf("%d\n",n);
// }
//return 0;
} int main(int argc, char* argv[]) {
printf("%d\n" , livetest(argv[]));
return ;
}
参考:
用C语言实现Ping程序功能:http://www.ibm.com/developerworks/cn/linux/network/ping/index.html
作者: NONO
出处:http://www.cnblogs.com/diligenceday/
QQ:287101329
微信:18101055830
linux:C语言通过ICMP协议判断局域网内部主机是否存活的更多相关文章
- PING的原理以及ICMP协议
主要内容: 1.ping的原理以及工作过程 2.ICMP协议 3.ICMP的应用:ping,traceroute 1.ping的原理以及工作过程 ping的原理 ping 程序是用来探测主机到主机 ...
- ping 原理与ICMP协议[转]
原文:http://blog.csdn.net/inject2006/article/details/2139149 ping 的原理 ping 程序是用来探测主机到主机之间是否可通信,如果不 ...
- ping 原理与ICMP协议
ping 的原理 ping 程序是用来探测主机到主机之间是否可通信,如果不能ping到某台主机,表明不能和这台主机建立连接.ping 使用的是ICMP协议,它发送icmp回送请求消息给目的主机 ...
- HCNP学习笔记之ICMP协议与ping原理以及用Python实现ping
一.ICMP协议分析 ICMP:Internet控制报文协议.由于IP协议并不是一个可靠的协议,它不保证数据被成功送达,那么,如何才能保证数据的可靠送达呢? 这里就需要使用到一个重要的协议模块ICMP ...
- ICMP协议 广播以查询局域网内的所有主机
看到了很多局域网内的主机扫描工具,在想怎么去实现这样一个工具.前几天看了Ping源码--ICMP协议的实例,ICMP可以用来探测网联网内的任一主机,ICMP和广播地址结合来扫描局域网内的所有主机不是很 ...
- Linux用ICMP协议实现简单Ping网络监测功能
ICMP是(Internet Control Message Protocol)Internet控制报文协议.它是TCP/IP协议族的一个子协议,用于在IP主机.路由器之间传递控制消息.控制消息是指网 ...
- IP封包协议头/TCP协议头/TCP3次握手/TCP4次挥手/UDP协议头/ICMP协议头/HTTP协议(请求报文和响应报文)/IP地址/子网掩码(划分子网)/路由概念/MAC封包格式
IP协议头IP包头格式: 1.版本号:4个bit,用来标识IP版本号.这个4位字段的值设置为二进制的0100表示IPv4,设置为0110表示IPv6.目前使用的IP协议版本号是4. 2.首部长度:4个 ...
- 利用ARP和ICMP协议解释ping命令
一.MTU 以太网和IEEE 802.3对数据帧的长度都有限制,其最大值分别是1500和1492字节,将这个限制称作最大传输单元(MTU,Maximum Transmission Unit).如果IP ...
- 计网-ping服务命令与ICMP协议
目录 一.IP协议的助手 —— ICMP 协议(网络层协议) 二.ping —— 查询报文类型的使用 三.traceroute —— 差错报文类型的使用 参考:从Wireshark抓包软件角度理解PI ...
随机推荐
- 1.2 如何使用LINQ
LINQ作为一种数据查询编码方式,它本身不是独立的开发语言,也不能进行应用程序开发.但是在.NET 4.5中,可以在C#中集成LINQ查询代码. 在任何源代码文件中,要使用LINQ查询功能,必须引用S ...
- Spring.Net+NHibenate+Asp.Net Mvc+Easyui框架
Spring.Net+NHibenate+Asp.Net Mvc+Easyui框架 初次接触Spring.Net+NHibenate+Asp.Net Mvc+Easyui框架,查阅了相关资料,了解了框 ...
- 曲演杂坛--一条DELETE引发的思考
原文:曲演杂坛--一条DELETE引发的思考 场景介绍: 我们有一张表,专门用来生成自增ID供业务使用,表结构如下: CREATE TABLE TB001 ( ID ,) PRIMARY KEY, D ...
- .NET编程和SQL Server ——Sql Server 与CLR集成 (学习笔记整理-1)
原文:.NET编程和SQL Server ——Sql Server 与CLR集成 (学习笔记整理-1) 一.SQL Server 为什么要与CLR集成 1. SQL Server 提供的存储过程.函数 ...
- AngularJs ng-repeat 必须注意的性能问题
AngularJs 的 ng-repeat 让我们非常方便的遍历数组生成 Dom 元素,但是使用不当也会有性能问题. 在项目中我们使用 ng-repeat 加载完一个列表后,如果再次请求数据,然后过滤 ...
- ASP.NET MVC 5项目
图文详解远程部署ASP.NET MVC 5项目 话外篇: 由于感觉自己的机器比较慢,配置不好,所以最近想把之前的项目部署到实验室的服务器上,但是由于常不在实验室,所以在想能不能远程部署.因此今天专 ...
- web 富文本编辑器总结
前言 富文本编辑器,就是除了能输入不同的文本之外,还可以之间粘贴图画等其他的多媒体信息.也可说是所见即所得的编辑器. 目前可以使用的编辑器有很多, 在网络上有找到这样一份比较表格: 编辑器 产地 稳定 ...
- iOS基础 - 多线程线程
一.多线程的应用 l 充分发挥多核处理器的优势,并发(同时执行)执行任务让系统运行的更快.更流畅 二.进程与线程概念 l 一个运行的程序就是一个进程或者叫做一个任务 l 一个进程至少包含一个线程,线程 ...
- 控制winform中控件的输入格式
private void txtNum1_KeyPress(object sender, KeyPressEventArgs e) { ') && e.KeyChar != '\r' ...
- c#中解决winform中控件不能输入汉字的办法
设置控件的ImeMode属性 如: textBox.ImeMode = System.Windows.Forms.ImeMode.On; 其中枚举有如下值: