IP数据包的解析

IP数据包的解析,第1张

改了一个问题,其他没错

另外,这里也不需要setsockopt

#include<iostream>

#include<winsock2.h>

#include<ws2tcpip.h>

#pragma comment(lib,"ws2_32")

#define IO_RCVALL _WSAIOW(IOC_VENDOR,1)

typedef struct IP_HEAD

{

union

{

unsigned char Version

unsigned char HeadLen

}

unsigned char ServiceType

unsigned short TotalLen

unsigned short Identifier

union

{

unsigned short Flags

unsigned short FragOffset

}

unsigned char TimeToLive

unsigned char Protocol

unsigned short HeadChecksum

unsigned int SourceAddr

unsigned int DestinAddr

unsigned char Options

}ip_head

void main(int argc,char *argv[])

{

using namespace std

if(argc!=2)

{

cout<<endl<<"请以下格式输入命令行:PackParse packet_sum"<<endl

return

}

WSADATA WSAData

if(WSAStartup(MAKEWORD(2,2), &WSAData)!=0)

{

cout<<endl<<"WSASTartup初始化失败"<<endl

return

}

SOCKET sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP)

if(sock==INVALID_SOCKET)

{

cout<<endl<<"创建Socket失败!"<<endl

goto exit_clean

}

BOOL flag=TRUE

if(setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char *) &flag,sizeof(flag))==SOCKET_ERROR)

{

cout<<endl<<"setsockopt *** 作失败:"<<WSAGetLastError()<<endl

goto exit_clean

}

char hostName[128]

if(gethostname(hostName,100)==SOCKET_ERROR)

{

cout<<endl<<"gethostname *** 作失败:"<<WSAGetLastError()<<endl

goto exit_clean

}

hostent *pHostIP

if((pHostIP=gethostbyname(hostName))==NULL)

{

cout<<endl<<"gethostbyname *** 作失败:"<<WSAGetLastError()<<endl

goto exit_clean

}

sockaddr_in host_addr

host_addr.sin_family=AF_INET

host_addr.sin_port=htons(6000)

host_addr.sin_addr=*(in_addr *)pHostIP->h_addr_list[0]

if(bind(sock,(PSOCKADDR)&host_addr,sizeof(host_addr))==SOCKET_ERROR)

{

cout<<endl<<"bind *** 作失败:"<<WSAGetLastError()<<endl

goto exit_clean

}

DWORD dwBufferLen[10]

DWORD dwBufferInLen=1

DWORD dwBytesReturned=0

if(WSAIoctl(sock , IO_RCVALL ,&dwBufferInLen , sizeof(dwBufferInLen) , &dwBufferLen,sizeof(dwBufferLen),&dwBytesReturned,NULL,NULL)==SOCKET_ERROR)

{

cout<<endl<<"WSAIoctl *** 作失败:"<<WSAGetLastError()<<endl

goto exit_clean

}

cout<<endl<<"开始解析IP包:"<<endl

char buffer[65535]

int packsum=atoi(argv[1])

for(int i=0i<packsumi++)

{

if(recv(sock,buffer,65535,0)>0)

{

ip_head ip=*(ip_head *)buffer

cout<<"-----------------------"<<endl

cout<<"版本:"<<(ip.Version>>4)<<endl

cout<<"头部长度:"<<((ip.HeadLen &0x0f)*4)<<endl

cout<<"服务类型:Priority"<<(ip.ServiceType>>5)<<", Service"<<((ip.ServiceType>>1)&0x0f)<<endl

cout<<"总长度:"<<ip.TotalLen<<endl

cout<<"标识符:"<<ip.Identifier<<endl

cout<<"标志位:"<<((ip.Flags>>15)&0x01)<<",DF= "<<((ip.Flags>>14)&0x01)<<",Mf="<<((ip.Flags>>13)&0x01)<<endl

cout<<"片偏移:"<<(ip.FragOffset&0x1fff)<<endl

cout<<"生存周期:"<<(int)ip.TimeToLive<<endl

cout<<"协议:Protocol"<<(int)ip.Protocol<<endl

cout<<"头部校验和:"<<ip.HeadChecksum<<endl

cout<<"原地址:"<<inet_ntoa(*(in_addr *)&ip.SourceAddr)<<endl

cout<<"目的IP地址:"<<inet_ntoa(*(in_addr *)&ip.DestinAddr)<<endl

}

}

exit_clean:

closesocket(sock)

WSACleanup()

}

首先要看version是引用类型,其肯定是返回参数。

b为Byte类型,其实就是二进制类型其样式为10011101,一共八个bit。b>>4就是移位运算,10011101 >>4 = 00001001(举例)

很明显,version版本存放在b的高4位中。

result = (b&0x0f)*4这个很明显是为了提取b的低四位数据,因为0x0f = (0000 1111)(B),然后乘以*4,就是左移2位,我擦楼主,你好好看看谭浩强的书吧!1 <<2 = 2^2 = 4

swith(b>>5)右移5位,和上面一样,如果是 1001 1101 >>5 = 0000 0100

后面的我就不说了,其实如果你理解前面的,后面的就都懂了。

楼猪,建议你看看谭浩强的书,位运算章节,不是很难。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7840227.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-10
下一篇 2023-04-10

发表评论

登录后才能评论

评论列表(0条)

保存