简单的实现了一个ping程序,没有做icmp差错报文的检查。

支持自定义字节数,支持发包个数

 #pragma pack(4)

 #define  ECHO_REQUEST        8
#define DATASIZE 65500
#define PACKETSIZE 65535 struct iphdr
{
unsigned char ip_hdr_len : ; //包头长度
unsigned char ip_version : ; //版本
unsigned char ip_tos; unsigned short ip_length; //总长度
unsigned short ip_identify;//标识
unsigned short ip_offset;//片偏移
unsigned char ip_ttl;
unsigned char ip_protocol;
unsigned short ip_cksum; struct in_addr ip_src; //源地址
struct in_addr ip_dst; //目的地址
}; struct icmphdr
{
unsigned char icmp_type; //8位类型
unsigned char icmp_code; //8位代码
unsigned short icmp_cksum; //16位的校验和 unsigned short icmp_identify;
unsigned short icmp_seq; LONGLONG icmp_timestamp;
char icmp_data[DATASIZE];
}; unsigned short checksum(int count,unsigned short* addr)
{
long sum = ; while(count > )
{
sum +=*addr++;
count -= sizeof(unsigned short);
} if(count > )
{
sum +=*(unsigned char*)addr;
} while(sum >> )
{
sum = (sum & 0xFFFF) + (sum >> );
} return (unsigned short)(~sum);
} void packet_pad(char * buf,int payload)
{
char pad[] = "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x7\x73\x74\x75\x76\x77"; int size = sizeof(pad) -;
int count = payload / size;
int remain = payload % size;
int offset = ; //偏移 memset((void *)buf,,payload); for(int i = ;i < count; ++i)
{
memcpy((void *)(buf + offset),(void *)pad,size);
offset += size;
} memcpy((void *)(buf + offset),(void *)pad,remain);
} LONGLONG getsystickcount64()
{
static LARGE_INTEGER tickspersecond = {};
LARGE_INTEGER tick; if(!tickspersecond.QuadPart)
{
QueryPerformanceFrequency(&tickspersecond);
} QueryPerformanceCounter(&tick); LONGLONG seconds = tick.QuadPart / tickspersecond.QuadPart;
LONGLONG leftPart = tick.QuadPart - (tickspersecond.QuadPart * seconds);
LONGLONG millseconds = ((leftpart << ) - ((leftpart << ) + (leftpart << ))) / tickspersecond.QuadPart;
LONGLONG ret = ((seconds << ) - ((seconds << ) + (seconds << ))) + millseconds; return ret;
}; bool ping(char * target,int payload,int count)
{
WSADATA wsaData;
WSAStartup(MAKEWORD(, ), &wsaData); SOCKET soc = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
if(soc == -)
{
printf("create raw socket failed!\n");
return false;
} if(payload > DATASIZE)
{
printf("发送的字节数有错误,有效范围从 0 到 %d",DATASIZE);
return false;
} payload = payload - sizeof(LONGLONG); struct sockaddr_in addrsrv; addrsrv.sin_family = AF_INET;
addrsrv.sin_port = htons();
struct hostent* phostent = gethostbyname(target);
if (phostent)
{
addrsrv.sin_addr.s_addr = *(u_long *)phostent->h_addr_list[];
} printf("正在 Ping %s [%s] 具有 %d 字节的数据: \n",target,inet_ntoa(addrsrv.sin_addr),payload + sizeof(LONGLONG)); icmphdr ihdr = {}; memset((void *)ihdr.icmp_data,,DATASIZE);
packet_pad(ihdr.icmp_data,payload); //填充数据 ihdr.icmp_type = ECHO_REQUEST;
ihdr.icmp_identify = (unsigned short)GetCurrentProcessId(); int hdr_len = payload + sizeof(icmphdr) - DATASIZE; struct timeval timeout;
struct sockaddr_in addrcli; char recv[PACKETSIZE] = {}; unsigned long interval = ;
unsigned long avgdelay = ;
unsigned long maxdelay = ;
unsigned long mindelay = ~; unsigned int sndcnt = count;
unsigned int loscnt = ; for(int seq = ; seq < count; ++seq)
{
memset((void *)recv,,PACKETSIZE); ihdr.icmp_seq = seq;
ihdr.icmp_cksum = ;
ihdr.icmp_timestamp = getsystickcount64(); //时间戳
ihdr.icmp_cksum = checksum(hdr_len,(unsigned short *)&ihdr); if(sendto(soc,(char *)&ihdr,hdr_len,,(sockaddr *)&addrsrv,sizeof(addrsrv)) == -)
{
--sndcnt;
continue;
} int nlength = sizeof(addrcli);
timeout.tv_sec = ;
timeout.tv_usec = ; setsockopt(soc, SOL_SOCKET,SO_RCVTIMEO, (char*)&timeout,sizeof(timeout)); if(recvfrom(soc,recv,PACKETSIZE,,(sockaddr *)&addrcli,&nlength) == -)
{
printf("请求超时!\n");
++loscnt;
continue;
} iphdr* piphdr = (iphdr *)recv;
if(checksum(piphdr->ip_hdr_len << ,(unsigned short *)piphdr) != )
{
printf("invalid ip packet!\n");
continue;
} icmphdr* pichdr = (icmphdr *)(piphdr + );
if(checksum(hdr_len,(unsigned short *)pichdr) != )
{
printf("invalid icmp packet!\n");
continue;
} interval = getsystickcount64() - pichdr->icmp_timestamp;
avgdelay+= interval; maxdelay = interval > maxdelay ? interval : maxdelay;
mindelay = interval > mindelay ? mindelay : interval; printf("来自 %s 的回复: 字节=%d 时间=%dms TTL=%u\n",inet_ntoa(addrsrv.sin_addr),payload + sizeof(LONGLONG),interval,piphdr->ip_ttl); Sleep();
} printf("\n");
printf("%s 的 Ping 统计信息: \n",inet_ntoa(addrsrv.sin_addr));
printf(" 数据包: 已发送 = %d, 已接收 = %d, 丢失 = %d (%.2f%% 丢失),\n",sndcnt,sndcnt-loscnt,loscnt,(loscnt * ) / (double)sndcnt);
printf("往返行程的估计时间(以毫秒为单位):\n");
printf(" 最短 = %dms, 最长 = %dms, 平均 = %dms\n",mindelay,maxdelay,avgdelay / sndcnt);
printf("\n");
} int main(int argc,char * argv[])
{
ping("www.baidu.com",,);
return ;
}

TCP协议学习记录 (二) Ping程序的更多相关文章

  1. TCP协议学习记录 (三) Ping程序 RR选项 记录路由hop

    一开始想直接在上个程序改,自己构造IP包头,但后来发现不行,微软不让干了,所以后来选用libcap库来收发包 代码写的很乱.. #pragma pack(4) #define ECHO_REQUEST ...

  2. TCP协议学习记录 (一) ICMP时间戳请求

    程序只实现了获取时间戳,至于将时间戳转换成具体日期和时间,暂时没有好的办法. #define TIME_STAMP_REQUEST 13 struct iphdr { unsigned ; //包头长 ...

  3. TCP/IP协议学习之实例ping命令学习笔记

    TCP/IP协议学习之实例ping命令学习笔记(一) 一. 目的为了让网络协议学习更有效果,在真实网络上进行ping命令前相关知识的学习,暂时不管DNS,在内网中,进行2台主机间的ping命令的整个详 ...

  4. [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序]

    [网络编程之Socket套接字介绍,套接字工作流程,基于TCP协议的套接字程序] 为何学习socket套接字一定要先学习互联网协议: 1.首先:要想开发一款自己的C/S架构软件,就必须掌握socket ...

  5. Material Calendar View 学习记录(二)

    Material Calendar View 学习记录(二) github link: material-calendarview; 在学习记录一中简单翻译了该开源项目的README.md文档.接下来 ...

  6. Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客

    ==他的博客应该不错,没有细看 Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客 http://blog.csdn.net/u012706811/article/det ...

  7. JavaScript学习记录二

    title: JavaScript学习记录二 toc: true date: 2018-09-13 10:14:53 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...

  8. 2.VUE前端框架学习记录二

    VUE前端框架学习记录二:Vue核心基础2(完结)文字信息没办法描述清楚,主要看编码实战里面,有附带有一个完整可用的Html页面,有需要的同学到脑图里面自取.脑图地址http://naotu.baid ...

  9. 网络协议学习笔记(二)物理层到MAC层,交换机和VLAN,ICMP与ping原理

    概述 之前网络学习笔记主要讲解了IP的诞生,或者说整个操作系统的诞生,一旦有了IP,就可以在网络的环境里和其他的机器展开沟通了.现在开始给大家讲解关于网络底层的相关知识. 从物理层到MAC层:如何在宿 ...

随机推荐

  1. LR12.53—第1课:构建Vuser脚本

    第1课:构建Vuser脚本 要生成系统上的负载,首先建立一个可以运行以模拟真实用户行为Vuser脚本.您使用VuGen创建和构建Vuser脚本. 在这一课中,你将涵盖以下主题: 介绍VuGen将 - ...

  2. 用rpm -e 将yum命令删除了,如何修复

    系统环境: 物理机:Windows 10 家庭中文版 虚拟机:VMware Workstation 10 Linux发行版本:CentOS 6.5 相关信息查询: 首先查询,系统安装的yum包的信息: ...

  3. Pycharm注册码

    name : newasp===== LICENSE BEGIN =====09086-1204201000001EBwqd8wkmP2FM34Z05iXch1AkKI0bAod8jkIffywp2W ...

  4. 【JAVA】【Eclipse】出现This element neither has attached source nor attached Javadoc...的解决方法

    This element neither has attached source nor attached Javadoc and hence no Javadoc could be found Ec ...

  5. Mybtis框架总结(一)

    一:Mybaits下载并搭建核心框架 1:下载mybatis的jar包: 2:创建mybatis框架链接数据库的配置文件Configuration.xml,格式如下 <!DOCTYPE conf ...

  6. UE4.11新特性:胶囊体阴影

    官方介绍 虚幻引擎现在支持非常柔滑的间接阴影,由代表角色的胶囊体来进行投影. 通常,在受间接光照时,并不会产生阴影,除非是屏幕空间环境遮罩.间接投影需要做的非常柔滑,因为间接光照是来自很多不同的方向, ...

  7. JS学习知我见(常用建站代码)

    <!doctype html><html><head><meta charset="utf-8"><meta name=&qu ...

  8. [JSP]解决Maven创建项目失败

    来源:http://lovespss.blog.51cto.com/1907593/522225 新建Maven项目时遇到这个错误: Unable to create project from arc ...

  9. 9.7 js进阶总结2

    数组元素添加 将一个或多个新元素添加到数组结尾,并返回数组新长度 var week_len = week.push(‘星期四’,‘星期五’); 将一个或多个新元素添加到数组开始,数组中的元素自动后移, ...

  10. web开发漫谈

    本文同步至微信公众号http://mp.weixin.qq.com/s?__biz=MzAxMzgwNDU3Mg==&mid=401950045&idx=1&sn=cec056 ...