多线程使用不同原始socket发送ICMP的问题,求教高手!
写了一个代码,下面简单举例:每个线程都有自己创建的原始socket:
m_Socket = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,
WSA_FLAG_OVERLAPPED);
然后每个线程都有不同的目的IP;
各自线程向目的IP发送ICMP检测报文(也就是ping包),每个线程发送后即刻调用recvfrom进行报文接收,如下:
ulByteRcvCnt = recvfrom(m_Socket, m_pRcvData, MAX_DATASIZE, 0,
(struct sockaddr*)&stIPSrc, &lSrcLen);
if(SOCKET_ERROR == ulByteRcvCnt)
{
ulLastError = WSAGetLastError();
if(WSAETIMEDOUT == ulLastError)
{
Lock();
m_TimeOutArray.Add(tNow);
UnLock();
}
}
else
{
pstIcmpHdr = (struct icmp *)(m_pRcvData + sizeof(IpHeader));
if((ICMP_ECHOREPLY == pstIcmpHdr->i_code)
&&(pstIcmpHdr->i_id == (USHORT)m_ulThreadId))
{
DelayMsInfo* pDelay = (DelayMsInfo*)malloc(sizeof(DelayMsInfo));
pDelay->tTime = tNow;
pDelay->ulDelay = (GetTickCount() - ulMsStart)+1;
Lock();
m_DelayMsArray.Add(pDelay);
UnLock();
}
else
{
assert(0);
}
}
但是最后出现了下面的问题:
线程A的socket_a向目的IP_A发出报文后,接收到的ICMP回复报文会被线程B的socket_b接收到,导致错误。见上面断言处:assert(0);
这里有几个疑惑:
1)难道原始socket在一个进程里面不能使用多个吗?若是一个进程里面使用多个,socket是如何区分的?(因为原始套接字不能像TCP/UDP那样绑定端口,是在不知道如何进行区分)
2) 原始套接字是否与进程号绑定了,也就是说原始socket只能在一个进程里有一个,多了就会乱?
请高手解答! --------------------编程问答-------------------- 下面发出自己的程序,麻烦高手看看,问题如何解决?
自己写的CIcmpsocket类简介:
1)通过构造函数得到目的IP,和接收icmp的超时时间,和持续发送的时长;
2)通过调用成员函数start来开始发包icmp探测的线程,也就是说一个类有自己的一个线程;
3)创建3个CIcmpsocket类的对象,赋予不同的目的IP,然后调用它们的start函数,使其开始进行各自的icmp探测;
结果出现3个线程互相收到不是自己的icmp回复报文。
麻烦高手解答
ULONG WINAPI IcmpSocketThreadProc(LPVOID lpParameter)
{
CIcmpSocket *pThread;
pThread = (CIcmpSocket *)lpParameter;
pThread->Execute();
ExitThread(0);
return 1;
}
CIcmpSocket::CIcmpSocket(DWORD ulDstIP, DWORD ulDataSize, DWORD ulRcvTimeO, DWORD ulTestTime)
{
m_Socket = INVALID_SOCKET;
int iTimeout = 2000;/*2S超时*/
DWORD ulLoop = 0;
struct sockaddr stAddr = {0};
m_ThreadHandle = NULL;
m_tTestTime = ulTestTime;
m_ulTimeOut = ulRcvTimeO;
m_ulThreadId = 0;
InitializeCriticalSection(&m_Section);
memset(&m_IPHdr, 0, sizeof(IpHeader));
memset(&m_IcmpHeader, 0, sizeof(IcmpHeader));
memset(&m_Dest, 0, sizeof(m_Dest));
if(INADDR_NONE == ulDstIP)
{
assert(0);
}
m_Dest.sin_family = AF_INET;
m_Dest.sin_addr.S_un.S_addr = ulDstIP;
m_ulDatasize = ulDataSize;
m_ulDatasize += sizeof(IcmpHeader);
m_pSndData = (char*)malloc(m_ulDatasize);
if(NULL == m_pSndData)
{
assert(0);
}
m_pRcvData = (char*)malloc(MAX_DATASIZE);
if(NULL == m_pRcvData)
{
assert(0);
}
//fill_icmp_data(m_pSndData, m_ulDatasize);
m_bTerminate = false;
}
CIcmpSocket::~CIcmpSocket()
{
if(m_Socket != INVALID_SOCKET)
{
closesocket(m_Socket);
m_Socket = INVALID_SOCKET;
}
Lock();
DWORD ulDelayCnt = m_DelayMsArray.GetSize();
DelayMsInfo* pstDelay = NULL;
for(DWORD ulLoop = 0; ulLoop < ulDelayCnt; ulLoop++)
{
pstDelay = (DelayMsInfo*)m_DelayMsArray[ulLoop];
if(NULL != pstDelay)
{
free((void*)pstDelay);
}
}
m_DelayMsArray.RemoveAll();
UnLock();
if(m_pSndData)
{
free(m_pSndData);
}
if(m_pRcvData)
{
free(m_pRcvData);
}
}
void CIcmpSocket::Execute()
{
int iTimeout = 0;
m_ulThreadId = GetCurrentThreadId();
if(WSAStartup(MAKEWORD(2,2), &m_wsaData) != 0)
{
assert(0);
}
m_Socket = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,
WSA_FLAG_OVERLAPPED);
if(INVALID_SOCKET == m_Socket)
{
assert(0);
}
iTimeout = (int)m_ulTimeOut;
if(SOCKET_ERROR == setsockopt(m_Socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&iTimeout, sizeof(iTimeout)))
{
assert(0);
}
iTimeout = 1000;
if(SOCKET_ERROR == setsockopt(m_Socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&iTimeout, sizeof(iTimeout)))
{
assert(0);
}
while(!m_bTerminate)
{
Run();
Sleep(10);
}
ExitThread(0);
return;
}
void CIcmpSocket::fill_icmp_data(char * icmp_data, int datasize)
{
IcmpHeader *icmp_hdr = NULL;
char *datapart = NULL;
icmp_hdr = (IcmpHeader*)icmp_data;
icmp_hdr->i_type = ICMP_ECHO; //类型为ICMP_ECHO
icmp_hdr->i_code = 0;
icmp_hdr->i_id = (USHORT)m_ulThreadId; //识别号为进程号
icmp_hdr->i_cksum = 0; //校验和初始化
icmp_hdr->i_seq = 0; //序列号初始化
datapart = icmp_data + sizeof(IcmpHeader); //数据端的地址为icmp报文地址加上ICMP的首部长度
memset(datapart, 'A', datasize - sizeof(IcmpHeader)); //这里我填充的数据全部为"A",你可以填充任何代码和数据,实际上木马和控制端之间就是通过数据段传递数据的。
return;
}
// CheckSum函数是标准的校验和函数
USHORT CIcmpSocket::CheckSum (USHORT *buffer, int size)
{
unsigned long cksum=0;
while(size >1)
{
cksum+=*buffer++;
size -=sizeof(USHORT);
}
if(size )
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}
void CIcmpSocket::Lock(void)
{
EnterCriticalSection(&m_Section);
return ;
}
void CIcmpSocket::UnLock(void)
{
LeaveCriticalSection(&m_Section);
return ;
}
void CIcmpSocket::Start()
{
if(NULL == m_ThreadHandle)
{
m_ThreadHandle = CreateThread(NULL,1000000, IcmpSocketThreadProc,(LPVOID)this,0,NULL);
}
return ;
}
void CIcmpSocket::Stop()
{
m_bTerminate = false;
}
bool CIcmpSocket::Run()
{
time_t tStart = time(NULL);
time_t tNow = tStart;
unsigned short usSeq = 0;
DWORD ulByteSndCnt = 0;
DWORD ulByteRcvCnt = 0;
struct sockaddr stIPSrc = {0};
int lSrcLen = sizeof(stIPSrc);
DWORD ulMsStart = 0;
DWORD ulLastError = 0;
DWORD ulLoop = 0;
while((tNow - tStart) <= m_tTestTime)
{
IcmpHeader* pstIcmpHdr = (IcmpHeader*)m_pSndData;
if( (GetTickCount()-ulMsStart) <= 2000)
{
Sleep(10);
continue;
}
fill_icmp_data(m_pSndData, m_ulDatasize);
pstIcmpHdr->i_cksum = 0;
pstIcmpHdr->timestamp = GetTickCount();
pstIcmpHdr->i_seq = usSeq;
pstIcmpHdr->i_cksum = CheckSum((unsigned short*)m_pSndData, m_ulDatasize);
ulMsStart = GetTickCount();
ulByteSndCnt = sendto(m_Socket, m_pSndData, m_ulDatasize, 0,
(struct sockaddr*)&m_Dest, sizeof(struct sockaddr));
if(SOCKET_ERROR == ulByteSndCnt)
{
ulLastError = WSAGetLastError();
if(WSAETIMEDOUT == ulLastError)
{
Lock();
m_TimeOutArray.Add(tNow);
UnLock();
continue;
}
return false;
}
if(ulByteSndCnt < m_ulDatasize)
{
continue;
}
memset((void*)m_pRcvData, 0, MAX_DATASIZE);
ulByteRcvCnt = recvfrom(m_Socket, m_pRcvData, MAX_DATASIZE, 0,
(struct sockaddr*)&stIPSrc, &lSrcLen);
if(SOCKET_ERROR == ulByteRcvCnt)
{
ulLastError = WSAGetLastError();
if(WSAETIMEDOUT == ulLastError)
{
Lock();
m_TimeOutArray.Add(tNow);
UnLock();
}
}
else
{
pstIcmpHdr = (struct icmp *)(m_pRcvData + sizeof(IpHeader));
if((ICMP_ECHOREPLY == pstIcmpHdr->i_code)
&&(pstIcmpHdr->i_id == (USHORT)m_ulThreadId))
{
DelayMsInfo* pDelay = (DelayMsInfo*)malloc(sizeof(DelayMsInfo));
pDelay->tTime = tNow;
pDelay->ulDelay = (GetTickCount() - ulMsStart)+1;
Lock();
m_DelayMsArray.Add(pDelay);
UnLock();
}
else
{
assert(0);
}
}
usSeq++;
tNow = time(NULL);
Sleep(10);
}
return true;
}
bool CIcmpSocket::GetStatistic(CDWordArray& TimeOutArray, CPtrArray& DelayMsArray)
{
DWORD ulDelayCnt = 0;
DWORD ulTimeOutCnt = 0;
DelayMsInfo* pstDelay = NULL;
DWORD ulLoop = 0;
Lock();
ulDelayCnt = m_DelayMsArray.GetSize();
ulTimeOutCnt = m_TimeOutArray.GetSize();
for(ulLoop = 0; ulLoop < ulDelayCnt; ulLoop++)
{
pstDelay = (DelayMsInfo*)m_DelayMsArray[ulLoop];
if(NULL != pstDelay)
{
DelayMsInfo* pRetDelay = (DelayMsInfo*)malloc(sizeof(DelayMsInfo));
memcpy(pRetDelay, pstDelay, sizeof(DelayMsInfo));
DelayMsArray.Add(pRetDelay);
}
}
for(ulLoop = 0; ulLoop < ulTimeOutCnt; ulLoop++)
{
TimeOutArray.Add(m_TimeOutArray[ulLoop]);
}
UnLock();
return true;
} --------------------编程问答-------------------- 自己顶一下
补充:.NET技术 , VC.NET