#include "stdafx.h"
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <tchar.h>#pragma comment (lib,"ws2_32")#define ICMP_UNREACH 3 //错误:目标不可达#define ICMP_UNREACH_NET 0 //
#define ICMP_UNREACH_HOST 1 //
#define ICMP_UNREACH_PROTO 2 //
#define ICMP_UNREACH_PORT 3 //端口访问不到#define ICMP_NET_UNKNOWN 6
#define ICMP_HOST_UNKNOWN 7#define MAXPACKET 4096// 
// IP header structure
//
typedef struct _iphdr 
{
    unsigned int   version:4;      // Version of IP
    unsigned int   h_len:4;        // Length of the header
    unsigned char  tos;            // Type of service
    unsigned short total_len;      // Total length of the packet
    unsigned short ident;          // Unique identifier
    unsigned short frag_and_flags; // 3位标志
   //13位片偏移
    unsigned char  ttl;            // Time to live
    unsigned char  proto;          // Protocol (TCP, UDP etc)
    unsigned short checksum;       // IP checksum    unsigned int   sourceIP;
    unsigned int   destIP;
} IpHeader;//
// ICMP header structure
//
typedef struct _icmphdr 
{
    BYTE   i_type;
    BYTE   i_code;                 // Type sub code
    USHORT i_cksum;
    USHORT i_id;
    USHORT i_seq;
    // This is not the standard header, but we reserve space for time
    ULONG  timestamp;
} IcmpHeader;void DisplayError( LPTSTR szAPI, DWORD dwError )
{
   LPTSTR lpBuffer = NULL;   FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
         FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,
         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
         (LPTSTR) &lpBuffer, 0, NULL );   _tprintf( TEXT("%s failed:\n"), szAPI );
   _tprintf( TEXT("    error code = %d\n"), dwError );
   _tprintf( TEXT("    message    = %s\n"), lpBuffer );   LocalFree( lpBuffer );
}
// ************************************************
//
//检查指定IP地址的UDP端口 
//返回值1 表示正常 
//-1表示 端口不存在 
//-2表示机器未在线  
// 0 表示函数出错
int check_udp(char* ipAddrerss,unsigned short portNumber)
{
int ret=0,fromlen,iplen;
WSADATA            wsaData;
struct sockaddr_in myudp,sockfrom;
SOCKET udpsock, rawsock;
IcmpHeader *packet;
IpHeader *iphdr;
char recvbuff[MAXPACKET];
char buff[] = "This was a blatant UDP port scan.";
int timeout = 1000;
int bwrite=0; udpsock = rawsock = INVALID_SOCKET; if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
DisplayError(TEXT("WSAStartup"),WSAGetLastError());
return 0;
}
//创建UDP套接字,用于发送UDP包
if((udpsock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) == INVALID_SOCKET)
    {
DisplayError(TEXT("socket"),WSAGetLastError());
goto Cleanup;
    } //创建原始套接字,接受IP包
    rawsock = WSASocket (AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,
                         WSA_FLAG_OVERLAPPED);
    if (rawsock == INVALID_SOCKET) 
    {
        DisplayError(TEXT("socket"),WSAGetLastError());
        goto Cleanup;
    }
//设置套接字接受的超时选项
if(setsockopt(rawsock,SOL_SOCKET,SO_RCVTIMEO,
(char*)&timeout,sizeof(timeout))==SOCKET_ERROR)
{
DisplayError(TEXT("setsockopt"),WSAGetLastError());
goto Cleanup;
}
timeout=1000;
if(setsockopt(rawsock,SOL_SOCKET,SO_SNDTIMEO,
(char*)&timeout,sizeof(timeout))==SOCKET_ERROR)
{
DisplayError(TEXT("setsockopt"),WSAGetLastError());
goto Cleanup;
}
//地址转换
if((myudp.sin_addr.s_addr = inet_addr(ipAddrerss)) == INADDR_NONE)
{
struct hostent *host;
if((host = gethostbyname(ipAddrerss)) == NULL)
{
printf("%s Invalid address\n",ipAddrerss);
    goto Cleanup;
}
    else
memcpy(&host->h_addr,&myudp.sin_addr.s_addr,host->h_length); 
} myudp.sin_family = AF_INET;
    myudp.sin_port = htons(portNumber); bwrite=sendto(udpsock,buff,sizeof(buff),0,(struct sockaddr *)&myudp,sizeof(myudp));
if(bwrite == SOCKET_ERROR )
{
DisplayError(TEXT("sendto"),WSAGetLastError());
goto Cleanup;
}
else
printf("write %d bytes!\n",bwrite); fromlen=sizeof(sockfrom);
if(recvfrom(rawsock,
recvbuff,
MAXPACKET,
0,
(struct sockaddr*)&sockfrom,
&fromlen) == SOCKET_ERROR )
{
DisplayError(TEXT("recvfrom"),WSAGetLastError());
goto Cleanup;
} iphdr = (IpHeader *)recvbuff;
iplen = iphdr->h_len * 4;
packet = (IcmpHeader *)(recvbuff + iplen); ret=1;
if(packet->i_type == ICMP_UNREACH)
{
switch(packet->i_code)
{
case ICMP_UNREACH_HOST:
ret=-2;
break;
case ICMP_UNREACH_PORT:
ret=-1;
break;
default:
break;
}
}Cleanup:
if (udpsock != INVALID_SOCKET) 
closesocket(udpsock);
if (rawsock != INVALID_SOCKET) 
closesocket(rawsock);
WSACleanup();  return ret;
}int main(int argc,char *argv[]) 
{
printf("check port :%d\n",check_udp("192.168.0.4",500));
return 0;
}