大家帮我看下这段ping的小程序哪里有问题?

堕落的乞讨者 2013-04-15 04:14:21

/*
* dealPing.cpp
*
* Created on: 2013-4-11
* Author: root
*/
#include <sys/select.h>
#include <unistd.h>
#include <sys/time.h>
#include "CoreCommon.h"
#include <ace/OS_NS_arpa_inet.h>
#include <string>

#define ICMP_ECHOREPLY 0
#define ICMP_ECHO 8
#define ICMP_TIMEOUT 11 // Time out ICMP Packet
#define REQ_DATASIZE 4096
#define MAXICMPLEN 4096
#define DEF_PACKET 32
#define MAXPACKET 65535 /*IP包的最大大小*/
#define UDPPACKETSIZE 36 /*UDP数据报的大小*/
#define SRCPORT 23156 /*UDP包的源端口*/
#define DSTPORT 5812 /*UDP包的目的端口*/

#define MAX_PATHLEN 255

//IP及ICMP包头部结构
typedef struct ip_head{
u32 HeadLen:4; //用32位字表示的报头长度
u32 version:4; //协议版本
u8 level; //优先级
u16 len; //包长度
u16 ID; //标识
u16 mflag; //其它标记
u8 ttl; //生命期
u8 prot; //协议
u16 cksum; //检查和
u32 sourIP; //源IP地址
u32 destIP; //目的IP地址
}IPHDR, *PIPHDR;

typedef struct tagICMPHDR
{
u8 Type; // Type
u8 Code; // Code
u16 Checksum; // Checksum
u16 ID; // Identification
u16 Seq; // Sequence
u16 number; //计数值
u16 time; //时间
char Data; //Data
} ICMPHDR, *PICMPHDR;

// ICMP Echo Request
typedef struct tagECHOREQUEST
{
ICMPHDR icmpHdr;
struct timeval echoTime;
char cData[1];
} ECHOREQUEST, *PECHOREQUEST;

// ICMP Echo Reply
typedef struct tagECHOREPLY
{
IPHDR ipHdr;
ECHOREQUEST echoRequest;
char cFiller[MAXICMPLEN];
} ECHOREPLY, *PECHOREPLY;

/****************************************************************************
函数名称:checksum
函数功能:计算校验和
输入:
buffer: 数据缓冲
size: 缓冲大小

输出:无
返回值: 校验和
特殊说明:
****************************************************************************/
u16 checksum(u16 *buffer, int size)
{
unsigned long cksum=0;
while(size >1)
{
cksum+=*buffer++;
size -=sizeof(unsigned short);
}
if(size)
{
cksum += *(unsigned char*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (unsigned short)(~cksum);
}

/*timeval*/
void tv_sub(struct timeval *out,struct timeval *in)
{
if( (out->tv_usec-=in->tv_usec)<0)
{
--out->tv_sec;
out->tv_usec+=1000000;
}
out->tv_sec-=in->tv_sec;
}

/****************************************************************************
函数名称:dealPing
函数功能:测试对应IP网络状况并将结果写入指定文件
输入:
_timeOutMsec 超时时间
_ip 需要检测的IP地址
_packLen 单次发送包的大小

输出:无
返回值: 0:成功
1:超时
2:网络不可达
特殊说明:
****************************************************************************/
int dealPing(u32 _ip, u32 _packLen = 64, u32 _timeOutMsec = 400)
{
int ret = 0,dwpid;
int sockfd;
struct sockaddr_in addrDest;
float spenttime;
u8 sSendPacket[MAXICMPLEN] = { 0 };
struct in_addr tmpaddr;

std::string ipString = "";
char tmpIp[16] = { 0 };
if (inet_ntop(AF_INET, &_ip, tmpIp, sizeof(tmpIp)))
ipString = tmpIp;

if (!_packLen || _packLen > 1472)
{
_packLen = 32;
}
if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
{
//LOG_ERROR("dealPing", "Create icmp socket fail");
printf("dealPing , Create icmp socket fail");
return sockfd;
}

addrDest.sin_addr.s_addr = _ip;
addrDest.sin_family = AF_INET;
bzero(&(addrDest.sin_zero), 8);
bzero(&tmpaddr, sizeof(tmpaddr));

ECHOREQUEST *pechoReq = (ECHOREQUEST *) sSendPacket;
pechoReq->icmpHdr.Type = ICMP_ECHO;
pechoReq->icmpHdr.Code = 0;
pechoReq->icmpHdr.ID = getpid();
dwpid = pechoReq->icmpHdr.ID;
int Seq = 0;

memset(pechoReq->cData, 0xa5, _packLen);

/*addrDest.sin_addr.s_addr = _ip;
addrDest.sin_family = AF_INET;
bzero(&(addrDest.sin_zero), 8);*/

pechoReq->icmpHdr.Seq = Seq++;
pechoReq->icmpHdr.Checksum = 0;
gettimeofday(&pechoReq->echoTime, NULL);
pechoReq->icmpHdr.Checksum = checksum((unsigned short*) pechoReq, _packLen + sizeof(pechoReq->icmpHdr) + sizeof(pechoReq->echoTime));
if ((ret = sendto(sockfd, sSendPacket, _packLen + sizeof(pechoReq->echoTime) + sizeof(pechoReq->icmpHdr), 0, (struct sockaddr *) &addrDest, sizeof(addrDest))) < 0)
{
//LOG_ERROR("dealPing", "sendto fail");
//printf("dealPing , sendto fail\n");
printf("dealPing , %s Destination Host Unreachable\n", ipString.c_str());
close(sockfd);
return ret;
}

ECHOREPLY icmpRecv;
struct timeval Timeout;
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
//Timeout.tv_sec = _timeOutMsec / 1000;
//Timeout.tv_usec = (_timeOutMsec % 1000) * 1000;
Timeout.tv_sec = 1;
Timeout.tv_usec = 0;
ret = select(sockfd + 1, &readfds, NULL, NULL, &Timeout);
if (ret > 0)
{
if (FD_ISSET(sockfd, &readfds) > 0)
{
socklen_t addr_len;
addr_len = sizeof(struct sockaddr);
memset(&icmpRecv, 0, sizeof(ECHOREPLY));
if ((ret = recvfrom(sockfd, (ECHOREPLY*) &icmpRecv, sizeof(tagECHOREPLY), 0, (struct sockaddr *) &addrDest, &addr_len)) <= 0)
{
//LOG_ERROR("dealPing", "recvfrom error");
printf("dealPing , recvfrom error\n");
close(sockfd);
return ret;
}

printf("Type:%d\n",icmpRecv.echoRequest.icmpHdr.Type);
printf("ID:%d\n",icmpRecv.echoRequest.icmpHdr.ID);

if (icmpRecv.echoRequest.icmpHdr.Type == ICMP_ECHOREPLY && (addrDest.sin_addr.s_addr == _ip) && (icmpRecv.echoRequest.icmpHdr.ID == dwpid))
{
gettimeofday(&icmpRecv.echoRequest.echoTime, NULL);
tv_sub(&icmpRecv.echoRequest.echoTime, &pechoReq->echoTime);
spenttime = icmpRecv.echoRequest.echoTime.tv_sec * 1000 + icmpRecv.echoRequest.echoTime.tv_usec * 0.001;
if (spenttime <= (float)_timeOutMsec)
{
//LOG_DEBUG("dealPing", "Connect Normally Id_seq = %d time=%4.3fms\n", icmpRecv.echoRequest.icmpHdr.Seq, spenttime);
printf("dealPing , Connect Normally Id_seq = %d time=%4.3fms\n", icmpRecv.echoRequest.icmpHdr.Seq, spenttime);
return ret;
}
else
{
//LOG_DEBUG("dealPing", "Request %u Time out!\n", _ip);
printf("dealPing , Request %s Time out!\n", ipString.c_str());
return 1;
}
}
else if ((icmpRecv.echoRequest.icmpHdr.Type == ICMP_ECHOREPLY) && (addrDest.sin_addr.s_addr != _ip) && (icmpRecv.echoRequest.icmpHdr.ID == dwpid))
{
//LOG_ERROR("dealPing", "%u Destination Host Unreachable\n", _ip);
printf("dealPing , %s Destination Host Unreachable\n", ipString.c_str());
return 1;
}
}
}
else
{
//LOG_ERROR("dealPing", "%u Destination Host Unreachable\n", _ip);
printf("dealPing , %s Destination Host Unreachable\n", ipString.c_str());
return 1;
}

close(sockfd);
return ret;
}

int main()
{
std::string _mIP = "192.168.10.91";
u32 _ip = 0;
inet_pton(AF_INET, _mIP.c_str(), (void *) &_ip);
u32 _packLen = 64;
u32 _timeOutMsec = 400;
//printf("_ip:%d\n",_ip);
//while(true)
//{
dealPing(_ip, _packLen, _timeOutMsec);
//sleep(1);
//}
return 0;
}

为什么recvfrom的时候返回的icmpRecv.echoRequest.icmpHdr.Type是ICMP_ECHO而不是ICMP_ECHOREPLY求高手帮忙看下?谢谢了
...全文
52 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧