原始套接字

来源:互联网 发布:淘宝88元xbox360手柄 编辑:程序博客网 时间:2024/06/11 00:32

原始套接字 运行在网络层IP,而一般套接字运行在传输层UDP或TCP。

创建原始套接字需要管理员权限,否则即使创建成功也可能在bind()时失败。

XP:

可以在注册表创建HKEY_LOCAL_MACHINE\System\CurrentControlSet\Service\Afd\Parameters\DisaleRaw-Security,类型DWORD,值1

Win7:

以管理员权限运行编译器即可


#include<stdio.h>
#include <winsock2.h>

#pragma comment(lib,"ws2_32")
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)

//TCP头部结构体
typedef struct _TCPHeader
{
USHORT sourcePort;
USHORT destinationPort;
ULONG sequenceNumber;
ULONG acknowledgeNumber;
UCHAR dataoffset;
UCHAR flags;
USHORT windows;
USHORT checksum;
USHORT urgentPointer;
}TCPHeader, *PTCPHeader;

//UDP头部结构体
typedef struct _UDPHeader
{
USHORT sourcePort;
USHORT destinationPort;
USHORT len;
USHORT checksum;
}UDPHeader, *PUDPHeader;

//IP头部结构体
typedef struct _IPHeader
{
UCHAR iphVerLen;
UCHAR ipTOS;
USHORT ipLength;
USHORT ipID;
USHORT ipFlags;
UCHAR ipTTL;
UCHAR ipProtocol;
USHORT ipChecksum;
ULONG ipSource;
ULONG ipDestination;
}IPHeader, *PIPHeader;

void DecodeTCPPacket(char *pData);
void DecodeUDPPacket(char *pData);
void DecodeIPPacket(char *pData);

void main()
{
WSAData ws;
char szHostName[56];//存放主机名
SOCKADDR_IN addr_in;//SOCKADDR_IN 地址结构体
struct hostent *pHost;
DWORD dwValue = 1;
char buffer[255];
int nRet;

WSAStartup(MAKEWORD(2,2),&ws);
SOCKET sRaw = socket(AF_INET,SOCK_RAW,IPPROTO_IP);//创建原始套接字
gethostname(szHostName,56);//取主机名
if((pHost = gethostbyname((char *)szHostName)) == NULL)//根据主机名返回一个struct hostent的地址信息结构体
return;

//初始化地址结构体 SOCKADDR_IN
addr_in.sin_family = AF_INET;
addr_in.sin_port = htons(0);
memcpy(&addr_in.sin_addr.S_un.S_addr,pHost->h_addr_list[0],pHost->h_length);

printf("bind to interface:%s\n",::inet_ntoa(addr_in.sin_addr));
if(bind(sRaw,(SOCKADDR *)&addr_in,sizeof(addr_in)) == SOCKET_ERROR)//绑定bind
{
return;
}

if(ioctlsocket(sRaw,SIO_RCVALL,&dwValue) != 0)//获取套接字操作参数
{
return;
}

while(1)
{
nRet = recv(sRaw,buffer,1024,0);//接受套接字
if(nRet > 0)
{
DecodeIPPacket(buffer);//解码IP数据包
}
}

closesocket(sRaw);
}


//解码TCP
void DecodeTCPPacket(char *pData)
{
TCPHeader *pTcpHdr = (TCPHeader *)pData;
printf("TCP Port:%d -> %d\n",ntohs(pTcpHdr->sourcePort),ntohs(pTcpHdr->destinationPort));//输出TCP端口号
}


void DecodeUDPPacket(char *pData)
{
UDPHeader *pUdpHdr = (UDPHeader *)pData;
printf("UDP Port:%d -> %d\n",ntohs(pUdpHdr->sourcePort),ntohs(pUdpHdr->destinationPort));//输出UDP端口号
}


void DecodeIPPacket(char *pData)
{
IPHeader *pIpHdr = (IPHeader *)pData;//IP首部结构体
in_addr source,destination;//地址结构体 记录 源、目的地址
char szSourceIp[32],szDestinationIp[32];
int nHeaderLen;//计算IP头部长度使用的变量

source.S_un.S_addr = pIpHdr->ipSource;//获得源IP地址
destination.S_un.S_addr = pIpHdr->ipDestination;//获得目的IP地址

strcpy(szSourceIp,::inet_ntoa(source));//转换后记录下源IP
strcpy(szDestinationIp,::inet_ntoa(destination));//转换后记录下目的IP

nHeaderLen = (pIpHdr->iphVerLen & 0xF)* sizeof(ULONG);//计算头部长度

//根据类型使用相应的解码程序
switch(pIpHdr->ipProtocol)
{
case IPPROTO_TCP:
{
DecodeTCPPacket(pData + nHeaderLen);//解码IP头部以后的部分(即TCP包)
break;
}
case IPPROTO_UDP:
{
DecodeUDPPacket(pData + nHeaderLen);//解码IP头部以后的部分(即UDP包)
break;
}
case IPPROTO_ICMP:
{
break;
}
default:
break;
}
}

原创粉丝点击