1.如代码,bind调用并不生效,没有任何报错信息,bind如果用if判断捕获soucket error可以看到是不生效的。
#include "ping.h"
#include
#define _WINSOCK_DEPRECATED_NO_WARNINGS
USHORT CPing::s_usPacketSeq = 0;
CPing::CPing() :m_szICMPData(NULL),m_bIsInitSucc(FALSE)
{
WSADATA WSAData;
//WSAStartup(MAKEWORD(2, 2), &WSAData);
if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
{
/如果初始化不成功则报错,GetLastError()返回发生的错误信息/
printf("WSAStartup() failed: %d\n", GetLastError());
return;
}
m_event = WSACreateEvent();
m_usCurrentProcID = (USHORT)GetCurrentProcessId();
//setsockopt(m_sockRaw);
/*if ((m_sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0)) != SOCKET_ERROR)
{
WSAEventSelect(m_sockRaw, m_event, FD_READ);
m_bIsInitSucc = TRUE;
m_szICMPData = (char*)malloc(DEF_PACKET_SIZE + sizeof(ICMPHeader));
if (m_szICMPData == NULL)
{
m_bIsInitSucc = FALSE;
}
}*/
m_sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0);
if (m_sockRaw == INVALID_SOCKET)
{
std::cerr << "WSASocket() failed:" << WSAGetLastError ()<< std::endl; //10013 以一种访问权限不允许的方式做了一个访问套接字的尝试。
}
else
{
WSAEventSelect(m_sockRaw, m_event, FD_READ);
m_bIsInitSucc = TRUE;
m_szICMPData = (char*)malloc(DEF_PACKET_SIZE + sizeof(ICMPHeader));
if (m_szICMPData == NULL)
{
m_bIsInitSucc = FALSE;
}
}
}
CPing::~CPing()
{
WSACleanup();
if (NULL != m_szICMPData)
{
free(m_szICMPData);
m_szICMPData = NULL;
}
}
BOOL CPing::Ping(DWORD m_ulSrcIP,DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout)
{
return PingCore(m_ulSrcIP,dwDestIP, pPingReply, dwTimeout);
}
BOOL CPing::Ping(char *m_ulSrcIP,char *szDestIP, PingReply *pPingReply, DWORD dwTimeout)
{
if (NULL != szDestIP)
{
return PingCore(inet_addr(m_ulSrcIP),inet_addr(szDestIP), pPingReply, dwTimeout);
}
return FALSE;
}
BOOL CPing::PingCore(DWORD m_ulSrcIP,DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout)
{
//判断初始化是否成功
if (!m_bIsInitSucc)
{
return FALSE;
}
//配置SOCKET,此处设置destip的参数
struct sockaddr_in sockaddrDest;
sockaddrDest.sin_family = AF_INET;
sockaddrDest.sin_addr.s_addr = dwDestIP;
int nSockaddrDestSize = sizeof(sockaddrDest);
printf("dst = %ld and %hd\n", (struct sockaddr *)&sockaddrDest, (struct sockaddr *)&sockaddrDest);
//配置socket,此处设置srcip的参数;
struct sockaddr_in sockaddrSrc;
sockaddrSrc.sin_family = AF_INET;
sockaddrSrc.sin_addr.s_addr = m_ulSrcIP;
printf("src = %ld and %hd\n", (struct sockaddr *)&sockaddrSrc, (struct sockaddr *)&sockaddrSrc);
int nSockaddrSrcSize = sizeof(sockaddrSrc);
bind(m_sockRaw, (struct sockaddr *)&sockaddrSrc, nSockaddrSrcSize);
//构建ICMP包
int nICMPDataSize = DEF_PACKET_SIZE + sizeof(ICMPHeader);
ULONG ulSendTimestamp = GetTickCountCalibrate();
USHORT usSeq = ++s_usPacketSeq;
memset(m_szICMPData, 0, nICMPDataSize);
ICMPHeader *pICMPHeader = (ICMPHeader*)m_szICMPData;
pICMPHeader->m_byType = ECHO_REQUEST;
pICMPHeader->m_byCode = 0;
pICMPHeader->m_usID = m_usCurrentProcID;
pICMPHeader->m_usSeq = usSeq;
pICMPHeader->m_ulTimeStamp = ulSendTimestamp;
pICMPHeader->m_usChecksum = CalCheckSum((USHORT*)m_szICMPData, nICMPDataSize);
//发送ICMP报文
if (sendto(m_sockRaw, m_szICMPData, nICMPDataSize, 0, (struct sockaddr*)&sockaddrDest, nSockaddrDestSize) == SOCKET_ERROR)
{
printf("sento error\n");
return FALSE;
}
//判断是否需要接收相应报文
if (pPingReply == NULL)
{
return TRUE;
}
char recvbuf[256] = { "\0" };
while (TRUE)
{
//接收响应报文
if (WSAWaitForMultipleEvents(1, &m_event, FALSE, 100, FALSE) != WSA_WAIT_TIMEOUT)
{
WSANETWORKEVENTS netEvent;
WSAEnumNetworkEvents(m_sockRaw, m_event, &netEvent);
if (netEvent.lNetworkEvents & FD_READ)
{
ULONG nRecvTimestamp = GetTickCountCalibrate();
int nPacketSize = recvfrom(m_sockRaw, recvbuf, 256, 0, (struct sockaddr*)&sockaddrDest, &nSockaddrDestSize);
if (nPacketSize != SOCKET_ERROR)
{
IPHeader *pIPHeader = (IPHeader*)recvbuf;
USHORT usIPHeaderLen = (USHORT)((pIPHeader->m_byVerHLen & 0x0f) * 4);
ICMPHeader *pICMPHeader = (ICMPHeader*)(recvbuf + usIPHeaderLen);
if (pICMPHeader->m_usID == m_usCurrentProcID //是当前进程发出的报文
&& pICMPHeader->m_byType == ECHO_REPLY //是ICMP响应报文
&& pICMPHeader->m_usSeq == usSeq //是本次请求报文的响应报文
)
{
pPingReply->m_usSeq = usSeq;
pPingReply->m_dwRoundTripTime = nRecvTimestamp - pICMPHeader->m_ulTimeStamp;
pPingReply->sum++;
if (pPingReply->m_dwRoundTripTime >= 1000 && pPingReply->m_dwRoundTripTime < 0) {//定义超时的时间
pPingReply->flag++;
}
pPingReply->m_dwBytes = nPacketSize - usIPHeaderLen - sizeof(ICMPHeader);
pPingReply->m_dwTTL = pIPHeader->m_byTTL;
return TRUE;
}
}
}
}
//超时
if (GetTickCountCalibrate() - ulSendTimestamp >= dwTimeout)
{
pPingReply->sum++;
pPingReply->flag++;
return FALSE;
}
}
}
USHORT CPing::CalCheckSum(USHORT *pBuffer, int nSize)
{
unsigned long ulCheckSum = 0;
while (nSize > 1)
{
ulCheckSum += *pBuffer++;
nSize -= sizeof(USHORT);
}
if (nSize)
{
ulCheckSum += (UCHAR)pBuffer;
}
ulCheckSum = (ulCheckSum >> 16) + (ulCheckSum & 0xffff);
ulCheckSum += (ulCheckSum >> 16);
return (USHORT)(~ulCheckSum);
}
ULONG CPing::GetTickCountCalibrate()
{
static ULONG s_ulFirstCallTick = 0;
static LONGLONG s_ullFirstCallTickMS = 0;
SYSTEMTIME systemtime;
FILETIME filetime;
GetLocalTime(&systemtime);
SystemTimeToFileTime(&systemtime, &filetime);
LARGE_INTEGER liCurrentTime;
liCurrentTime.HighPart = filetime.dwHighDateTime;
liCurrentTime.LowPart = filetime.dwLowDateTime;
LONGLONG llCurrentTimeMS = liCurrentTime.QuadPart / 10000;
if (s_ulFirstCallTick == 0)
{
s_ulFirstCallTick = GetTickCount();
}
if (s_ullFirstCallTickMS == 0)
{
s_ullFirstCallTickMS = llCurrentTimeMS;
}
return s_ulFirstCallTick + (ULONG)(llCurrentTimeMS - s_ullFirstCallTickMS);
}
错误的代码如下:
//配置socket,此处设置srcip的参数;
struct sockaddr_in sockaddrSrc;
sockaddrSrc.sin_family = AF_INET;
sockaddrSrc.sin_addr.s_addr = m_ulSrcIP;
printf("src = %ld and %hd\n", (struct sockaddr *)&sockaddrSrc, (struct sockaddr *)&sockaddrSrc);
int nSockaddrSrcSize = sizeof(sockaddrSrc);
bind(m_sockRaw, (struct sockaddr *)&sockaddrSrc, nSockaddrSrcSize);
如下:
//创建用于监听的套接字
SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.s_addr = htonl(INADDR_ANY);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(m_usPort); //m_usPort是一个unsigned short 类型的端口号
//绑定套接字
bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));