Windows 2000下的Raw Socket编程

Windows2000在TCP/IP协议组件上做了很多改进,功能也有增强 。比如在协议栈上的调整,增大了默认窗口大小,以及高延迟链接新算法 。同时在安全性上,可应用IPSec加强安全性,比NT下有不少的改进 。

Microsoft TCP/IP 组件包含“核心协议”、“服务”及两者之间的“接口” 。传输驱动程序接口 (TDI) 与网络设备接口规范 (NDIS) 是公用的 。此外,还有许多用户模型应用程序的更高级接口 。最常用的接口是 Windows Sockets、远程过程调用 (RPC) 和 NetBIOS 。

Windows Sockets 是一个编程接口,它是在加州大学伯克利分校开发的套接字接口的基础上定义的 。它包括了一组扩展件,以充分利用 Microsoft Windows 消息驱动的特点 。规范的 1.1 版是在 1993 年 1 月发行的,2.2.0 版在 1996 年 5 月发行 。Windows 2000 支持 Winsock 2.2 版 。在Winsock2中,支持多个传输协议的原始套接字,重叠I/O模型、服务质量控制等 。

这 里介绍Windows Sockets的一些关于原始套接字(Raw Socket)的编程 。同Winsock1相比,最明显的就是支持了Raw Socket套接字类型,通过原始套接字,我们可以更加自如地控制Windows下的多种协议,而且能够对网络底层的传输机制进行控制 。

1、创建一个原始套接字,并设置IP头选项 。

SOCKET sock;
sock = socket(AF_INET,SOCK_RAW,IPPROTO_IP);
或者:
s = WSASoccket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED);

这 里,我们设置了SOCK_RAW标志,表示我们声明的是一个原始套接字类型 。创建原始套接字后,IP头就会包含在接收的数据中,如果我们设定 IP_HDRINCL 选项,那么,就需要自己来构造IP头 。注意,如果设置IP_HDRINCL 选项,那么必须具有 administrator权限,要不就必须修改注册表:
HKEY_LOCAL_MacHINESystemCurrentControlSetServicesAfdParameter
修改键:DisableRawSecurity(类型为DWord),把值修改为 1 。如果没有,就添加 。

BOOL blnFlag=TRUE;
setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&blnFlag, sizeof(blnFlag);

对于原始套接字在接收数据报的时候,要注意这么几点:
1、如果接收的数据报中协议类型和定义的原始套接字匹配,那么,接收的所有数据就拷贝到套接字中 。
2、如果绑定了本地地址,那么只有接收数据IP头中对应的远端地址匹配,接收的数据就拷贝到套接字中 。
3、如果定义的是外部地址,比如使用connect(),那么,只有接收数据IP头中对应的源地址匹配,接收的数据就拷贝到套接字中 。


2、构造IP头和TCP头

这里,提供IP头和TCP头的结构:
// Standard TCP flags
#define URG 0x20
#define ACK 0x10
#define PSH 0x08
#define RST 0x04
#define SYN 0x02
#define FIN 0x01
typedef struct _iphdr //定义IP首部
{
unsigned char h_lenver; //4位首部长度 4位IP版本号
unsigned char tos; //8位服务类型TOS
unsigned short total_len; //16位总长度(字节)
unsigned short ident; //16位标识
unsigned short frag_and_flags; //3位标志位
unsigned char ttl; //8位生存时间 TTL
unsigned char proto; //8位协议 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校验和
unsigned int sourceIP; //32位源IP地址
unsigned int destIP; //32位目的IP地址
}IP_HEADER;

typedef struct psd_hdr //定义TCP伪首部
{
unsigned long saddr; //源地址
unsigned long daddr; //目的地址
char mbz;
char ptcl; //协议类型
unsigned short tcpl; //TCP长度
}PSD_HEADER;

typedef struct _tcphdr //定义TCP首部
{
USHORT th_sport; //16位源端口
USHORT th_dport; //16位目的端口
unsigned int th_seq; //32位序列号
unsigned int th_ack; //32位确认号
unsigned char th_lenres; //4位首部长度/6位保留字
unsigned char th_flag; //6位标志位

推荐阅读