使用原始套接字:SOCK_RAW

需要ICMP

代码如下:

#include<iostream>
#include<WinSock2.h> using namespace std; #pragma comment(lib, "WS2_32.lib") typedef struct icmp_hdr{
unsigned char icmp_type;
unsigned char icmp_code;
unsigned short icmp_checksum;
unsigned short icmp_id;
unsigned short icmp_sequence;
unsigned long icmp_timnestamp;
}ICMP_HDR, *PICMP_HDR; typedef struct _IPHeader{
UCHAR iphVerLen;
UCHAR ipTOS;
USHORT ipLength;
USHORT ipID;
USHORT ipFlags;
UCHAR ipTTL;
UCHAR ipProtocol;
USHORT ipChecksum;
ULONG ipSource;
ULONG ipDestination;
}IPHeader, *PIPHeader; USHORT checksum(USHORT* buffer, int size)
{
unsigned long cksum = 0; while(size > 1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
} // 奇数,将最后一个字节扩展到双字, 再累加
if(size)
cksum += *(UCHAR*)buffer; //高16 低16相加,取反
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return (USHORT)(~cksum);
} int main(void)
{
char szDestIp[] = "127.0.0.1";
SOCKET sRaw= ::socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
//SetTimeout(sRaw, 1000, TRUE); SOCKADDR_IN dest;
dest.sin_family = AF_INET;
dest.sin_port = htons(5674);
dest.sin_addr.S_un.S_addr = inet_addr(szDestIp); char buff[sizeof(ICMP_HDR) + 32];
ICMP_HDR *pIcmp = (ICMP_HDR*)buff;
pIcmp->icmp_type = 8;
pIcmp->icmp_code = 0;
pIcmp->icmp_id = (USHORT)::GetCurrentProcess();
pIcmp->icmp_checksum = 0;
pIcmp->icmp_sequence = 0;
memset(&buff[sizeof(ICMP_HDR)], 'E', 32); //发送
USHORT nSeq = 0;
char recvBuf[1024];
SOCKADDR_IN from;
int nLen = sizeof(from);
while(TRUE)
{
static int nCount = 0;
int nRet;
if(nCount++ == 4)
break;
pIcmp->icmp_checksum = 0;
pIcmp->icmp_timnestamp = ::GetTickCount();
pIcmp->icmp_sequence = nSeq++;
pIcmp->icmp_checksum = checksum((USHORT*)buff, sizeof(ICMP_HDR) + 32);
nRet = ::sendto(sRaw, buff, sizeof(ICMP_HDR) + 32, 0, (SOCKADDR*)&dest, sizeof(dest));
if(nRet == SOCKET_ERROR)
{
cout << "sendto error:" << ::WSAGetLastError() << endl;
return -1;
} nRet = ::recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*)&from, &nLen);
if(nRet == SOCKET_ERROR)
{
if(::WSAGetLastError() == WSAETIMEDOUT)
{
cout << "time out" << endl;
continue;
}
cout << "recvfrom failed:" << ::WSAGetLastError() << endl;
return -1;
} //解析
int nTick = ::GetTickCount();
if(nRet < sizeof(IPHeader) + sizeof(ICMP_HDR))
{
cout << "Too few bytes from " << ::inet_ntoa(from.sin_addr) << endl;
} ICMP_HDR *pRecvIcmp = (ICMP_HDR*)(recvBuf + sizeof(IPHeader));
if(pRecvIcmp->icmp_type != 0)
{
cout << "nonecho type " << pRecvIcmp->icmp_type << " recvd" << endl;
return -1;
}
if(pRecvIcmp->icmp_id != ::GetCurrentProcessId())
{
cout << "someone ele's packet!" << endl;
return -1;
} cout << nRet << " bytes from " << inet_ntoa(from.sin_addr) ;
cout << "icmp_seq = " << pRecvIcmp->icmp_sequence ;
cout << "time: " << nTick - pRecvIcmp->icmp_timnestamp << " ms";
cout << endl;
Sleep(1000);
} return 0;
}

jofranks  13.7.24 于南昌

【网络编程】之十三、ping程序实现的更多相关文章

  1. Socket网络编程--小小网盘程序(5)

    各位好呀!这一小节应该就是这个小小网盘程序的最后一小节了,这一节将实现最后的三个功能,即列出用户在服务器中的文件列表,还有删除用户在服务器中的文件,最后的可以共享文件给好友. 列出用户在服务器中的文件 ...

  2. C#网络编程TCP通信实例程序简单设计

    C#网络编程TCP通信实例程序简单设计 采用自带 TcpClient和TcpListener设计一个Tcp通信的例子 只实现了TCP通信 通信程序截图: 压力测试服务端截图: 俩个客户端链接服务端测试 ...

  3. Linux 网络编程基础(4) -- Ping 的C代码实现

    1.背景 在进行网络编程的时候,通常使用的协议有TCP协议,UDP协议.这些协议在简历套接字之初需要制定套接字的类型,比如TCP应当设置为 SOCK_STREAM, UDP对应的套接字应当设置为SOC ...

  4. JAVA 网络编程 - 实现 群聊 程序

    在实现 这个 程序之前, 我们 需要 了解 一些 关于 Java 网络 编程 的 知识. 基本 的 网络知识: 网络模型 OSI (Open System Interconnection 开放系统互连 ...

  5. UNIX网络编程---TCP客户/服务器程序示例(五)

    一.概述 客户从标准输入读入一行文本,并写给服务器 服务器从网络输入读入这行文本,并回射给客户 客户从网络输入读入这行回射文本,并显示在标准输出上 二.TCP回射服务器程序:main函数 这里给了函数 ...

  6. python网络编程(十三)

    协程-greenlet版 为了更好使用协程来完成多任务,python中的greenlet模块对其封装,从而使得切换任务变的更加简单 安装方式 使用如下命令安装greenlet模块: sudo pip ...

  7. Socket网络编程--小小网盘程序(1)

    这个系列是准备讲基于Linux Socket进行文件传输.简单的文件传输就是客户端可以上传文件,可以从服务器端下载文件.就这么两个功能如果再加上身份验证,就成了FTP服务器了,如果对用户的操作再加上一 ...

  8. Socket网络编程--小小网盘程序(4)

    在这一小节中实现了文件的下载,具体的思路是根据用户的uid和用户提供的文件名filename联合两张表,取得md5唯一标识符,然后操作这个标识符对应的文件发送给客户端. 实现下载的小小网盘程序 cli ...

  9. 第5章-unix网络编程 TCP/服务端程序示例

    这一章主要是完成一个完整的tcp客户/服务器程序.通过一很简单的例子.弄清客户和服务器如何启动,如何终止,发生了某些错误会发生什么.这些事很重要的  客户端代码 #include "unp. ...

  10. 基于JAVA网络编程的聊天小程序

    package com.neusoft.edu.socket; import java.io.BufferedReader; import java.io.IOException; import ja ...

随机推荐

  1. python 使用 urllib2

    使用basic auth 的3种方式 1. 设置header import urllib2 from base64 import encodestring headers = {'Content-Ty ...

  2. ubuntu14.04 配置tomcat8

    ubuntu下配置tomcat的过程事实上和windows是差点儿相同的,以下一起来看一下怎样在ubuntu14.04中配置tomcat. 1.下载tomcat 地址:http://tomcat.ap ...

  3. python——PEP8 Python 编码规范整理

    决定开始Python之路了,利用业余时间,争取更深入学习Python.编程语言不是艺术,而是工作或者说是工具,所以整理并遵循一套编码规范是十分必要的.所以今天下午我根据PEP 8整理了一份,以后都照此 ...

  4. libevent2源码分析之一:前言

    event的本质 libevent2中的event的本质是什么?只要是非同步阻塞的运行方式,肯定遵循事件的订阅-发布模型.通过event_new的函数原型可以理解,一个event即代表一次订阅,建立起 ...

  5. 51单片机 | 1-Wire总线及应用实例

    ———————————————————————————————————————————— 1-Wire总线 - - - - - - - - - - - - - - - - - - - - - - - ...

  6. Linux下配置两个或多个Tomcat启动

    Linux下配置两个或多个Tomcat启动 (2012-08-14 11:59:31) 转载▼ 标签: 杂谈 分类: linux_tomcat 步骤如下: (1)修改/etc/profile文件.添加 ...

  7. C语言-EOF和feof()判断文件结尾的区别

    今天获取一个图片内容时, fopen("aaaaaa.png", "r"), 读取完文件头就停止了, 后来模式改为 "rb" 就可以了, 特 ...

  8. 纪念我人生中第一个merge into语句

    做按组织关系汇总功能时,当数据量特别大,或者汇总组织特别多时,运行效率特别低,于是使用了merge into语句. 代码如下: public void updateInsertData(DataSet ...

  9. gitlab 6 安装备忘录

    gitlab 6.2-stable;Ubuntu 13.10;ruby 2.0.0 推荐使用PostgreSQL,MySQL不同版本可能碰到兼容性问题(www.oschina.net/question ...

  10. Atitit.编程语言新特性 通过类库框架模式增强 提升草案 v3 q27

    Atitit.编程语言新特性 通过类库框架模式增强 提升草案 v3 q27 1. 修改历史2 2. 适用语言::几乎所有编程语言.语言提升的三个渠道::语法,类库,框架,ide2 2.1. 单根继承  ...