#include <iostream>
#include <winsock.h>
#include <string>
#include <sstream>
#pragma comment(lib,"Ws2_32.lib")
using namespace std;
USHORT checksum(USHORT* buff, int size)
{
unsigned long cksum = 0;
while (size > 1)
{
cksum += *buff++;
size -= sizeof(USHORT);
}
// 是奇数
if (size)
{
cksum += *(UCHAR*)buff;
}
// 将32位的chsum高16位和低16位相加,然后取反
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return (USHORT)(~cksum);
}
typedef struct icmp_hdr
{
unsigned char icmp_type; // 消息类型
unsigned char icmp_code; // 代码
unsigned short icmp_checksum; // 校验和
// 下面是回显头
unsigned short icmp_id; // 用来惟一标识此请求的ID号,通常设置为进程ID
unsigned short icmp_sequence; // 序列号
unsigned long icmp_timestamp; // 时间戳
} ICMP_HDR, *PICMP_HDR;
int SetTimeout(SOCKET s, int nTime, BOOL bRecv)
{
int ret = ::setsockopt(s, SOL_SOCKET,
bRecv ? SO_RCVTIMEO : SO_SNDTIMEO, (char*)&nTime, sizeof(nTime));
return ret != SOCKET_ERROR;
}
//检查主机IP是否ping通
bool PingIP(string szDestIP)
{
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(1, 1);
if (WSAStartup(wVersionRequested, &wsaData))
{
printf("Winsock Initialization failed.\n");
exit(1);
}
SOCKET sRaw = ::socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
SetTimeout(sRaw, 1000, TRUE);
SOCKADDR_IN dest;
dest.sin_family = AF_INET;
dest.sin_port = htons(0);
dest.sin_addr.S_un.S_addr = inet_addr(szDestIP.c_str());
char buff[sizeof(ICMP_HDR) + 32];
ICMP_HDR * pIcmp = (ICMP_HDR *)buff;
pIcmp->icmp_type = 8;
pIcmp->icmp_code = 0;
pIcmp->icmp_id = (USHORT)::GetCurrentProcessId();
pIcmp->icmp_checksum = 0;
pIcmp->icmp_sequence = 0;
memset(&buff[sizeof(ICMP_HDR)], 'E', 32);
USHORT nSeq = 0;
char revBuf[1024];
SOCKADDR_IN from;
int nLen = sizeof(from);
static int nCount = 0;
int nRet;
pIcmp->icmp_checksum = 0;
pIcmp->icmp_timestamp = ::GetTickCount();
pIcmp->icmp_sequence = nSeq++;
pIcmp->icmp_checksum = checksum((USHORT *)buff, sizeof(ICMP_HDR) + 32);
nRet = ::sendto(sRaw, buff, sizeof(ICMP_HDR) + 32, 0, (SOCKADDR *)&dest, sizeof(dest));
if (nRet == SOCKET_ERROR)
{
printf("sendto() failed:%d\n", ::WSAGetLastError());
return false;
}
nRet = ::recvfrom(sRaw, revBuf, 1024, 0, (sockaddr *)&from, &nLen);
if (nRet == SOCKET_ERROR)
{
cout << szDestIP << " ping failed." << endl;
return false;
}
cout << szDestIP << " ping success." << endl;
closesocket(nRet);
WSACleanup();
return true;
}
// 检查指定IP的端口是否打开
bool PingIPPort(string Ipaddr, int Port)
{
int mysocket;
struct sockaddr_in my_addr;
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(1, 1);
if (WSAStartup(wVersionRequested, &wsaData))
{
cout << "Winsock Initialization failed." << endl;
return false;
}
if ((mysocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
cout << "socket is invalid." << endl;
return false;
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(Port);
my_addr.sin_addr.s_addr = inet_addr(Ipaddr.c_str());
if (connect(mysocket, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == SOCKET_ERROR)
{
cout << "failed to open the port." << endl;
closesocket(mysocket);
return false;
}
closesocket(mysocket);
WSACleanup();
return true;
}
int str2int(string str)
{
istringstream is(str);
int i;
is >> i;
return i;
}
int main()
{
cout << "Please input \"IP:Port:\"";
string str;
cin >> str;
string strIp = str.substr(0, str.find_last_of(':'));
string strPort = str.substr(str.find_last_of(':') + 1, str.size() - 1);
int Port = str2int(strPort);
PingIP(strIp);
if (PingIPPort(strIp, Port))
cout << str << " is open." << endl;
else
cout << str << " is closed." << endl;
system("pause");
return 0;
}
C++判断主机IP和指定端口是否能Ping通
最新推荐文章于 2024-07-09 19:47:50 发布