typedef struct _IPHEADER //IP头结构
{
unsigned char header_len:4; //IP头大小,4个字节存放
unsigned char version:4; //IP版本,4个字节存放
unsigned char tos; //服务类型
unsigned short total_len; //数据报大小
unsigned short ident; //数字报标识
unsigned short flags; //一种标志
unsigned char ttl;
unsigned char proto; //协议
unsigned short charSum; //IP数据包检验
unsigned int sourceIP; //源ip
unsigned int destIP; //目的ip
}IPHEADER;
struct TCPPacketHead //传输控制协议头结构
{
WORD SourPort ; //源端口
WORD DestPort; //目的端口
WORD SeqNo; //序列号
DWORD AckNo;
BYTE HLen ; //头大小
BYTE Flag; //标志
WORD WndSize;
WORD ChkSum; //校验位
WORD UrgPtr;
};
struct UDPPacketHead //数据包包头结构
{
WORD SourPort; //源端口
WORD DestPort; //目的端口
WORD Len; //头大小
WORD ChkSum; //校验位
};
struct TCMPPacketHead //ICMP网际控制报文协议
{
BYTE Type; //协议类型
BYTE Code;
WORD ChkSum; //校验
};
int iRet = 0;
char buf[1000];
char* bufwork;
IPHEADER* pIpHeader;
in_addr ina;
char szSource[16], szDest[16], szErr[50];
char* pSource, *pDest;
char* pLastBuf = NULL;
WORD sourport, destport;
int HdrLen, totallen;
struct TCPPacketHead * pTCPHead;
struct TCMPPacketHead* pICMPHead;
struct UDPPacketHead* pUDPHead;
BYTE* pData = NULL;
while(true) //死循环
{
//检测消息队列中的WM_CLOSE消息
memset(buf, 0, sizeof(buf)); //初始化字符数组
//接收数据
iRet = recv(pDlg->m_socket, buf, sizeof(buf), 0);
if(*buf)
{
bufwork = buf; //字符串赋值
pIpHeader = (IPHEADER*)bufwork; //获取ip包的头
WORD iLen= ntohs(pIpHeader->total_len); //获得数据包大小
while(true) //嵌套死循环分析数据
{
if(iLen < iRet) //如果数据报大小小于接收到的数据大小
{
ina.S_un.S_addr = pIpHeader->sourceIP; //获取源ip
pSource = inet_ntoa(ina); //将网络ip转化为主机上的源ip地址
strcpy(szSource, pSource);
ina.S_un.S_addr = pIpHeader->destIP; //获取目标ip
pDest = inet_ntoa(ina); //将网络ip转化为主机上的目标ip地址
strcpy(szDest, pDest);
CString str, strProto, strSourPort, strDestPort, strData, strSize;
//得到数据报的协议名称
// strProto = get_proto_name(pIpHeader->proto);
HdrLen = pIpHeader->header_len&0xf; //获得IP头大小
HdrLen *= 4;
totallen = ntohs(pIpHeader->total_len); //获得数据报大小,转化为主机
totallen -= HdrLen; //数据包大小除去IP头大小
//对不同协议的头部数据进行分析
switch(pIpHeader->proto)
{
case IPPROTO_ICMP: //网际控制报文协议
{
pICMPHead = (struct TCMPPacketHead*)(buf+HdrLen); //获取除去IP头的ICMP报文
strSourPort = "-";
strDestPort = "-";
pData = ((BYTE*)pICMPHead) + ICMP_HEAD_LEN; //保存出去ICMP头的字节内容
totallen -= ICMP_HEAD_LEN; //总大小出去IP头和ICMP头后
break;
}
case IPPROTO_TCP: //传输控制协议
{
pTCPHead = (struct TCPPacketHead *)(buf+HdrLen); //获取除去IP头的TCP报文
sourport = ntohs(pTCPHead->SourPort); //得到源端口和目的端口号
destport = ntohs(pTCPHead->DestPort);
strSourPort.Format("%d",sourport );
strDestPort.Format("%d",destport);
HdrLen = (pTCPHead->HLen)>>4;
HdrLen *= 4;
pData = ((BYTE*)pTCPHead) +HdrLen; // //保存出去TCP头的字节内容
totallen -= HdrLen; //总大小出去IP头和TCP头后
break;
}
case IPPROTO_UDP:
{
pUDPHead = (struct UDPPacketHead*)(buf+HdrLen); //获取除去IP头的UDP报文
sourport = ntohs(pUDPHead->SourPort); //得到源端口和目的端口号
destport = ntohs(pUDPHead->DestPort);
strSourPort.Format("%d",sourport );
strDestPort.Format("%d",destport);
pData = ((BYTE*)pTCPHead) +UDP_HEAD_LEN; // //保存除去UDP头的字节内容
totallen -= UDP_HEAD_LEN; //总大小出去IP头和UDP头后
break;
}
}
// CString strSize, strData;
strSize.Format("%d",totallen );
strData.Format("%s", pData);
pDlg->AddData("", szSource, strSourPort, szDest, strDestPort,strSize, strData);
if(iLen < iRet) //保证获取完整的ip包
{
iRet -= iLen;
bufwork += iLen;
pIpHeader = (IPHEADER*)bufwork; //获取ip包的头
}
else
break; //如果pIpHeader->total_len == iRet就退出
}
else //如果pIpHeader->total_len ,已经读到buffer的最后部分,就是i包的长度
{
int iLast = iLen -iRet; //剩余的数据
pLastBuf = new char[iLen];
int iReaden = iRet; //已经达到的数据
memcpy(pLastBuf, bufwork, iReaden); //已经到达的数据
iRet = recv(pDlg->m_socket, pLastBuf+iReaden, iLast, 0) //继续接收剩余的数据,并存入之前的总接收包中,从iReaden处开始
bufwork = pLastBuf; //记录总的接收数据
pIpHeader = (IPHEADER*)bufwork; //改变获取ip包的头
if(iRet !=iLast ) //如果还是没有接收完剩余数据.,就读
{
iReaden+=iRet; //已经到达的数据
iLast -= iRet; // 剩余的数据
while(true)
{
//继续接收剩余的数据,并存入之前的总接收包中,从iReaden处开始
iRet = iRet = recv(pDlg->m_socket, pLastBuf+iReaden, iLast, 0) ;
iReaden+=iRet; //已经到达的数据
iLast -= iRet; // 剩余的数据
if(iLast <= 0)
{
break;
}