1. 程式人生 > >ping 程式(vc6.0 原始套接字實現)

ping 程式(vc6.0 原始套接字實現)

#include <stdio.h>
#include <WINSOCK2.H>
#include <windows.h>


#include <ws2tcpip.h> //IP_TTL
#pragma comment(lib,"ws2_32.lib")
//ICMP首部結構體
typedef struct tagICMPHEADER
{
 unsigned char type;//型別
 unsigned char code;//程式碼
 unsigned short checknum;//檢驗和
 unsigned short id;//識別符號
 unsigned short seq_num;//序列號
}ICMPHEADER;
//IP首部結構體
typedef struct _ip_hdr
{
 unsigned char ihl:4;   //首部長度
 unsigned char version:4, //版本 
 unsigned char tos;   //服務型別
 unsigned short tot_len; //總長度
 unsigned short id;    //標誌
 unsigned short frag_off; //分片偏移
 unsigned char ttl;   //生存時間
 unsigned char protocol; //協議
 unsigned short chk_sum; //檢驗和
 struct in_addr srcaddr; //源IP地址
 struct in_addr dstaddr; //目的IP地址
}IPHEADER;


//計算檢驗和
unsigned short checksum(unsigned short *buffer, int size) 
{ 
 unsigned long cksum = 0; // 將所有的16數相加 
 while (size > 1) 
 { 
  cksum += *buffer++;
  size -= sizeof(unsigned short); 
 }
 if (size) //加上最後一個BYTE 
 {
  cksum += *(unsigned char*)buffer;
 } 
 while (cksum>>16)
 {
  cksum = (cksum & 0xffff) + (cksum >> 16);
 } 
 return (unsigned short)~cksum;
} 
 
 
int main()
{
 WSADATA wsadata;
 if(WSAStartup(MAKEWORD(2,2),&wsadata)!=0)
 {
  printf("初始化socket dll失敗\n");
  return 1;
 }
 //設定ICMP首部內容
 ICMPHEADER icmp_hdr;
 icmp_hdr.type=8;
 icmp_hdr.code=0;
 icmp_hdr.checknum=0;
 icmp_hdr.id=(unsigned short)GetCurrentProcessId();
 icmp_hdr.seq_num=0;
 //計算檢驗和
 icmp_hdr.checknum=checksum((unsigned short*)&icmp_hdr,sizeof(icmp_hdr));
 //設定原始套接字
 SOCKET sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,0);
 if(INVALID_SOCKET==sock)
 {
  printf("建立socket失敗\n");
  WSACleanup();
  return 1;
 }
 int ttl=255;
 //設定TTL為255
 if(setsockopt(sock,IPPROTO_IP,IP_TTL,(const char*)&ttl,sizeof(ttl))==SOCKET_ERROR)
 {
  printf("set TTL error!\n");
  WSACleanup();
  return 2;
 }
 //目標地址
 SOCKADDR_IN Dest_addr;
 memset(&Dest_addr,0,sizeof(Dest_addr));
 Dest_addr.sin_family=AF_INET;
 Dest_addr.sin_addr.S_un.S_addr=inet_addr("192.168.1.1");
 //傳送ICMP請求報文
 int status=sendto(sock,(const char*)&icmp_hdr,sizeof(icmp_hdr),0,(SOCKADDR*)&Dest_addr,sizeof(Dest_addr));
 if(SOCKET_ERROR==status)
 {
  printf("sent error!\n");
  shutdown(sock,SD_BOTH);
  closesocket(sock);
  WSACleanup();
  return 3;
 }
 int size=60+sizeof(ICMPHEADER);
 char *buffer=(char*)malloc(size);
 memset(buffer,0,size);
 int des=sizeof(SOCKADDR_IN);
 //接受ICMP迴應報文並分析
 while (true)
 {
  recvfrom(sock,buffer,size,0,(SOCKADDR*)&Dest_addr,&des);
  ICMPHEADER *p=(ICMPHEADER*)((char*)buffer+((IPHEADER*)buffer)->ihl*4);
  if(p->type==0)
  {
   if(p->id==icmp_hdr.id)
   {
    printf("ping %s成功\n",inet_ntoa(Dest_addr.sin_addr));
    break;
   }
  }
  else
  {
   printf("ping %s不成功\n",inet_ntoa(Dest_addr.sin_addr));
   break;
  }
 }
 shutdown(sock,SD_BOTH);
 closesocket(sock);
 WSACleanup();
 return 0;
}