c语言 读ttl socket,基于C语言与原始套接字兑现Ping程序

基于C语言与原始套接字实现Ping程序

源代码如下:

ping.h

#pragma pack(1)

//#define u_char unsigned char

//#define u_short unsigned short

#include

#define ICMP_ECHOREPLY 0

#define ICMP_ECHOREQ 8

//

typedef struct tagIPDR

{

u_char VIHL;//版本和类型

u_char TOS;//服务质量

u_char shortTotLen;//长度

u_char shortID;//编号

u_char shortFlagOff;//分片,Fragment

u_char TTL;//生存时间

u_char Protocol;//协议类型

u_short Checksum;//校验和

struct in_addr iaSrc;//源地址

struct in_addr isDet;//目的地址

}IPHDR,*PIPHDR;//RFC791 的IP协议头类型

typedef struct tagICMP

{

u_char Type;//类型

u_char Code;//代号

u_short Checksum;//校验号

u_short ID;//标识号

u_short Seq;//列号

char Data;//数据信息

}ICMPHDR,*PICMPHDR;//RFC 792 ICMP协议头

/

#define REQ_DATASIZE 32

typedef struct tagECHOREQUEST

{

ICMPHDR icmpHdr;//ICMP协议头

DWORD dwTime;//数据传输时间

char cData[REQ_DATASIZE];//传输数据

}ECHOREQUEST,*PECHOREQUEST;//请求回传的数据长度

///

typedef struct tagECHOREPLY

{

IPHDR ipHdr;

ECHOREQUEST echoRequest;

char cFiler[256];

}ECHOREPLY,*PECHOREPLY;//回送请求报文

#pragma pack()

ping.cpp

#include "ping.h"

#include

#include

#include

DWORD time;

void Ping(LPCSTR pstrHost);//ping 指令函数;

void ReportError(LPCSTR psrtFrom);

int WaitForEchoReply(SOCKET s);

int SendEchoRequest(SOCKET,LPSOCKADDR_IN);

DWORD RecvEchoReply(SOCKET,LPSOCKADDR_IN,char*);

u_short in_cksum(u_short *addr,int len);

void main()

{

WSADATA wsaData;

WORD version=MAKEWORD(1,1);

char pstrHost[20];

if(WSAStartup(version,&wsaData))

{

printf("初始化协议栈错误\n");

getchar();

return ;

}

if(wsaData.wVersion!=version)

{

printf("不支持WIDOWS的套接字\n");

getchar();

return ;

}

bool flag=true;

while(flag)

{

printf("Ping>:");

scanf("%s",pstrHost);

if(strcmp(pstrHost,"exit")==0)

break;

printf("*****************************\n");

Ping(pstrHost);

}

WSACleanup();

}

void Ping(LPCSTR pstrHost)

{

SOCKET rawSocket;

LPHOSTENT lpHost;

struct sockaddr_in saDest;

struct sockaddr_in saSrc;

DWORD dwTimeSent;

DWORD dwElapsed;

u_char cTTL;

int nLoop;

int nRet;

rawSocket=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);

if(rawSocket==SOCKET_ERROR)

{

ReportError("套接字");

return;

}

lpHost=gethostbyname(pstrHost);

if(lpHost==NULL)

{

printf("无法找到这主机[%s]\n",pstrHost);

getchar();

return;

}

saDest.sin_addr.s_addr=*((u_long FAR*)(lpHost->h_addr));

saDest.sin_family=AF_INET;

saDest.sin_port=0;

printf("\n探测主机%s[%s]:%d字节\n",pstrHost,inet_ntoa(saDest.sin_addr),REQ_DATASIZE);

for(nLoop=0;nLoop<4;nLoop++)

{

SendEchoRequest(rawSocket,&saDest);

nRet=WaitForEchoReply(rawSocket);

if(nRet==SOCKET_ERROR)

{

ReportError("选择");

break;

}

if(!nRet)

{

printf("发送超时\n");

break;

}

dwTimeSent=RecvEchoReply(rawSocket,&saSrc,(char*)&cTTL);

dwElapsed=time-dwTimeSent;

printf("来自主机[%s]响应,字节:%d 时间:%ld毫秒 最大生存期:%d\n",inet_ntoa(saSrc.sin_addr),REQ_DATASIZE,dwElapsed,cTTL);

}

if(closesocket(rawSocket)==SOCKET_ERROR)

ReportError("关闭套接字");

}

int SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr)

{

static ECHOREQUEST echoReq;

static nId=1;

static nSeq=1;

static nRet;

echoReq.icmpHdr.Type=ICMP_ECHOREQ;

echoReq.icmpHdr.Code=0;

echoReq.icmpHdr.Checksum=0;

echoReq.icmpHdr.ID=nId++;

echoReq.icmpHdr.Seq=nSeq++;

for(nRet=0;nRet

echoReq.cData[nRet]=nRet;

echoReq.dwTime=GetTickCount();

time=echoReq.dwTime;//记录发送时间

echoReq.icmpHdr.Checksum=in_cksum((u_short *)&echoReq,sizeof(ECHOREQUEST));

nRet=sendto(s,(LPCSTR)&echoReq,sizeof(ECHOREQUEST),0,(LPSOCKADDR)lpstToAddr,sizeof(SOCKADDR_IN));

if(nRet==SOCKET_ERROR)

ReportError("发送出错");

return nRet;

}

void ReportError(LPCSTR lpStr)

{

printf("%s发生错误,错误号:%d\n",lpStr,WSAGetLastError());

getchar();

}

DWORD RecvEchoReply(SOCKET s,LPSOCKADDR_IN lpsaFrom,char *pTTL)

{

ECHOREPLY echoReply;

int nRet;

int nAddrLen=sizeof(struct sockaddr_in);

nRet=recvfrom(s,(LPSTR)&echoReply,sizeof(ECHOREPLY),0,(LPSOCKADDR)lpsaFrom,&nAddrLen);

if(nRet==SOCKET_ERROR)

ReportError("接收");

*pTTL=echoReply.ipHdr.TTL;

return echoReply.echoRequest.dwTime;

}

int WaitForEchoReply(SOCKET s)

{

struct timeval Timeout;

fd_set readfds;

readfds.fd_count=1;

readfds.fd_array[0]=s;

Timeout.tv_sec=5;

Timeout.tv_usec=0;

return select(1,&readfds,NULL,NULL,&Timeout);

}

u_short in_cksum(u_short *addr,int len)

{

register int nleft=len;

register u_short *w=addr;

register u_short answer;

register int sum=0;

while(nleft>1)

{

sum+=*w++;

nleft-=2;

}

if(nleft==1)

{

u_short u=0;

*(u_char *)(&u)=*(u_char *)w;

sum+=u;

}

sum=(sum>>16)+(sum&0xffff);

sum+=(sum>>16);

answer=~sum;

return answer;

}基于VC++6.0直接编译即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值