原始套接字

原始套接字 运行在网络层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;
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值