//定义ICMP报头结构 typedef struct icmp" /> 问题:C实现ping命令,错误代码10060
描述:

c语言socketwindows

代码功能主要是实现ping功能 ,可接收时老是出现错误码为10060  代码与错误截图如下
#include
#include
#pragma comment(lib,"ws2_32.lib")
#include
//定义ICMP报头结构
typedef struct icmp_head{
unsigned char icmp_type; //消息类型
unsigned char icmp_code;  //代码
unsigned short icmp_checksum;  //校验和
unsigned short icmp_id;  //表示请求的id号,通常设置为进程号
unsigned short icmp_sequence;  //序列号
unsigned int icmp_timestamp;  //时间戳
}ICMP_HEAD,*PICMP_HEAD;
//首先要计算校验和
unsigned short checksum(PICMP_HEAD picmp,int nSize){   //picmp为指向整个报文头部的指针
long sum=0;
unsigned short * pusIcmp=(unsigned short *)picmp;
while(nSize>1){
sum+=*(pusIcmp++);
nSize-=sizeof(USHORT);
}
if(nSize){
sum+= *(unsigned char *)pusIcmp;
}
//高16位与低16位相加,取反得到校验和
sum=(sum>>16)+(sum&&0xffff);
sum+=(sum>>16);
return (unsigned short)~sum;   //取反
}  //结束校验
int main(int argc, char* argv[]){   //argc是参数个数
//存放windows socket初始化信息,例如版本号,WinSock支持的最高版本
WSADATA wsaData;
SOCKET client;//原始套接字
SOCKADDR_IN destAddr;      //套接字地址家族,又称为套接字地址形式
struct hostent * host=NULL; //hostent是host entry的缩写,该结构记录主机的信息,包括主机名、别名、地址类型、地址长度和地址列表
    int nTimeOut=100000;
char szSendBuffer[sizeof(ICMP_HEAD)+32]={0};  //定义发送缓冲区,32是ICMP数据长度
char szRecvBuffer[1024];
PICMP_HEAD picmp=(PICMP_HEAD)szSendBuffer;   //PICMP指向发送缓冲区
if(argc<2){          //如果小于两个参数
printf("请输入目标主机的名称或IP地址!\n");
system("PAUSE");
return 1;
}
//加载动态链接库 
WSAStartup(MAKEWORD(2,2),&wsaData);   //表示使用WINSOCK2版本
    //创建原始套接字
//参数分别代表地址描述,套接口类型描述,套接字使用的协议,返回值代表成功与否
client = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
if(client==INVALID_SOCKET){
printf("socket()失败!错误码:%d\n",WSAGetLastError());
system("pause");
}
else{
printf("SOCKET创建成功!");
}
//设置接收超时时间,选项名:接收超时 选项值,char* 选项长度
setsockopt(client,SOL_SOCKET,SO_RCVTIMEO,(const char *)&nTimeOut,sizeof(nTimeOut));
//设置目标主机的地址
host=gethostbyname(argv[1]);
if(host==NULL){
printf("主机名解析失败!\n");
system("pause");
return 1;
}
destAddr.sin_family=AF_INET;
destAddr.sin_addr.S_un.S_addr=*((unsigned long *)host->h_addr);//
destAddr.sin_port=htons(0);  //WINDOWS套接口实现将给应用程序分配一个值在1024到5000之间的唯一的端口。
//ICMP_HEAD的封装
picmp->icmp_type=8;
picmp->icmp_code=0;
picmp->icmp_checksum=0;
picmp->icmp_id=(unsigned short)GetCurrentProcessId();    //当前发起请求的进程ID
//封装数据
memcpy((szSendBuffer + sizeof(ICMP_HEAD)),"ABCDABCDABCDABCDABCDABCDABCDABCD",32);
//计算校验和  利用内存copy函数
picmp->icmp_checksum=checksum((PICMP_HEAD)szSendBuffer,sizeof(szSendBuffer));
//向目标主机发送ICMP报文并接收回应报文
struct sockaddr_in fromAddr;
int sizeFrom=sizeof(SOCKADDR_IN);
memset(szRecvBuffer,0,1023);   //先清空接收的缓冲区
//向目标主机发送一个ICMP报文
//sendto() 用来将数据由指定的socket 传给对方主机
int sendBytes = sendto(client,szSendBuffer,sizeof(szSendBuffer),0,(SOCKADDR *)&destAddr,sizeof(destAddr));
    if(sendBytes==SOCKET_ERROR){
printf("发送错误:错误码%d\n",WSAGetLastError());
        system("pause");
return 1;
}
else{
printf("发送ICMP报文成功!发送的字节数:%d\n",sendBytes);
}
//从目标主机接收回应的ICMP报文
int recivBytes = recvfrom(client,szRecvBuffer,sizeof(szRecvBuffer),0,(SOCKADDR *)&fromAddr,&sizeFrom);
if(recivBytes==SOCKET_ERROR){
printf("接收错误:错误码:%d\n",WSAGetLastError());
system("pause");
return 1;
}
else{
printf("接收成功!收到的字节数:%d\n",recivBytes);
PICMP_HEAD PTEMP=(PICMP_HEAD)szRecvBuffer+20;   //跳过IP报文头部
DWORD t2=GetTickCount();
int time=t2-picmp->icmp_timestamp;//经过的时间
int datalen=recivBytes-20-sizeof(ICMP_HEAD);//发送的字节数
if(strcmp(inet_ntoa(fromAddr.sin_addr),inet_ntoa(destAddr.sin_addr))==0){  //保持地址一致
printf("来自%s的回复:字节=%d 时间=%d ms\n",inet_ntoa(destAddr.sin_addr),datalen,time);
}
}
system("pause");
return 0;
}
 ping 命令,linux ping命令,ping命令详解,ping ip命令,ping端口命令,ping大包命令,cmd ping 命令,ping命令的使用,tnsping命         

上一篇网络抓包工具原理
下一篇如何从数据包中判断该数据包是流入主机还是从主机流出?
明星图片
相关文章
《C实现ping命令,错误代码10060》由码蚁之家搜集整理于网络,
联系邮箱:mxgf168#qq.com(#改为@)