Ⅰ 清除本机的ARP地址缓存表,绑定本机的IP地址和MAC地址,要详细步骤,本人急需
开始-运行-输入CMD 打开了DOS系统
然后一次输入 arp -d  回车
arp -s 本机IP 本机MAC 回车
arp -s 网关IP 网管MAC 回车
注意格式 用空格隔开。
然后输入 arp -a  如果显示有static 即绑定成功
有时一次不行, 需要反复输入几次,若嫌麻烦,可以建立个批处理文件,步骤为新建记事本文件,然后输入
@echo off
arp -d
arp -s 本机IP 本机MAC 回车
arp -s 网关IP 网管MAC 回车
保存后,修改修改文件后缀为.bat
以后运行这个文件就行了,也可将此文件设置开机启动。不过个人觉得不是很好用。我每次都是手动输入的。
楼主试试吧。纯手工打的
Ⅱ Windows系统下能否通过原始套接字发送接受Arp数据包,如何操作(最好给个例子)
虽然Windows XP SP2已经不再支持原始TCP数据包的发送,但就其本身作为一项技术而言,掌握原始数据包的发送也是非常重要的。今天我们要讨论的原始UDP数据包的构造,便是这项技术的应用。相信懂得了如何管理UDP头,其他协议的封装应该就不成问题了。在阅读本文,你需要具备以下知识:熟悉C语言、Socket基础知识和TCP/IP基础知识。如果你已经掌握了上面的知识,那就让我们行动吧。 
                          数据包格式 
在对数据包进行封装之前,我们有必要了解一下数据报格式,图1是IP头格式。我们所学的知识绝大部分都是从资料书籍中来的,但资料毕竟是死的,当我们拿到图 1所表示的格式时,似乎有点蒙——这个格式是什么意思啊?怎么看?我记得我初学的时候就老犯这种糊涂。下面具体说明一下。 
javascript:dcs.images.doResizes(this,0,null);" src="/kf/UploadFiles_7205/201009/20100923105017273.jpg">
图1 
在认识该格式之前,我们有必要了解一下什么是“大尾”,什么是“小尾”。“大尾”就是高位字节排放在内存的低端,低位字节排放在内存的高端。“小尾”反之。 Intel处理器大多数使用小尾字节序,Motorola处理器大多数使用大尾(Big Endian)字节序。既然不同的处理器处理的方式不一样,那么在网络交流数据的时候便应该使用同一套标准,不然肯定会发生错误的。TCP/IP各层协议将字节序定义为大尾,因此TCP/IP协议中使用的字节序通常称之为网络字节序,因而在填充数据包的时候一定要注意字节顺序,不然会出错!还有,图1的数据是从左至右字节由低向高,这一点注意一下,初学者容易犯错。 
上面是一些需要注意的地方,下面再说一下各个字段的含义。 
1)版本号:标志版本; 
  2)分组长度(HLEN):报文头部的字数(字长=32bits); 
  3)业务类型(Type of Service):分组的处理方式; 
  4)总长度(Total Length):分组头部和数据的总长度(字节数); 
  5)标识(Identification)、标记(Flags)、片偏移(Frag Offset):对分组进行分片,以便允许网上不同MTU时能进行传送; 
  6)生存时间(TTL):规定分组在网上传送的最长时间(秒),防止分组无休止地要求网络搜寻不存在的目的地址; 
  7)协议(Protocol):发送分组的上层协议号(TCP= 6,UDP=17); 
  8)校验和(Header Checksum):分组头校验和; 
  9)源和目的IP地址(Source and Destination IP Address):标识网络终端设备的IP地址; 
  10)IP选项(IP Options):网络测试、调试、保密及其他; 
  11)数据(Data):上层协议数据。 
根据上面的说明我们可以定义以下IP头结构。 
typedef struct _IPHeader // 20字节的IP头 
{ 
UCHAR iphVerLen; // 版本号和头长度(各占4位) 
UCHAR ipTOS;  // 服务类型 
USHORTipLength; // 封包总长度,即整个IP报的长度 
USHORTipID; // 封包标识,惟一标识发送的每一个数据报 
USHORTipFlags; // 标志 
UCHAR ipTTL; // 生存时间,就是TTL 
UCHAR ipProtocol // 协议,可能是TCP、UDP、ICMP等 
USHORTipChecksum; // 校验和 
ULONG ipSource; // 源IP地址 
ULONG ipDestination; // 目的IP地址 
} IPHeader, *PIPHeader; 
有了IP头,下面就应该是UDP头了,如图2所示。下面说一下各个字段的含义。 
   javascript:dcs.images.doResizes(this,0,null); border=0> 
图2 
1)源端口(Source Port):呼叫端端口号; 
2)目的端口(Destination Port):被叫端端口号; 
3)报头长度(HLEN):报文头部的字节数; 
4)校验和(Checksum):报头和数据字段的校验和; 
5)数据(Data):上层协议数据。 
下面是定义的UDP头结构。 
typedef struct _UDPHeader 
{ 
USHORT         sourcePort;                // 源端口号 
USHORT         destinationPort;// 目的端口号 
USHORT         len;                        // 封包长度 
USHORT         checksum;                // 校验和 
} UDPHeader, *PUDPHeader; 
上面我详细介绍了IP头和UDP头的格式。在我们填充数据包的时候,应该清楚IP头、UDP头和传输数据的顺序应该与如图3一致。 
   
图3 
   编程 实现 
下面我们来看看发送原始UDP封包的代码是如何实现的。首先我们要有一个IP校验码,这有前人写好的专门代码,我们不必深究,拿来用就行,再此不贴出来,大家看杂志相关即可。下面是主程序的代码,很简单,大家慢慢体会,相信会有所收获的。 
int main() 
{// 输入参数信息 
char szDestIp[] = "88.88.88.88"; 
// <<== 填写目的IP地址 
char szSourceIp[] = "127.0.0.1"; 
// <<== 填写你自己的IP地址 
USHORT nDestPort = 4567;  //目的端口 
USHORT nSourcePort = 8888;//源端口 
char szMsg[] = "大家好,我是Hokkien!/r/n"; 
int nMsgLen = strlen(szMsg); 
// 创建原始套节字 
SOCKET sRaw = ::socket(AF_INET, SOCK_RAW, IPPROTO_UDP); 
// 有效IP头包含选项 
BOOL bIncl = TRUE; 
::setsockopt(sRaw, IPPROTO_IP, IP_HDRINCL, (char *)&bIncl, sizeof(bIncl)); 
char buff[1024] = { 0 }; 
// 填充IP头 
IPHeader *pIphdr = (IPHeader *)buff; 
pIphdr->iphVerLen = (4<<4 | (sizeof(IPHeader)/sizeof(ULONG))); 
//版本与长度 
pIphdr->ipLength = ::htons(sizeof(IPHeader) + sizeof(UDPHeader) + nMsgLen); 
//数据包长度 
pIphdr->ipTTL = 128;  //生存时间 
pIphdr->ipProtocol = IPPROTO_UDP;//UDP 
pIphdr->ipSource = ::inet_addr(szSourceIp);   //源IP 
pIphdr->ipDestination = ::inet_addr(szDestIp);  //目的IP 
pIphdr->ipChecksum = checksum((USHORT*)pIphdr, sizeof(IPHeader)); 
//校验码,这是必需的! 
// 填充UDP头 
UDPHeader *pUdphdr = (UDPHeader *)&buff[sizeof(IPHeader)]; 
pUdphdr->sourcePort = htons(8888);   //源端口 
pUdphdr->destinationPort = htons(nDestPort);//目的端口 
pUdphdr->len = htons(sizeof(UDPHeader) + nMsgLen);//报头长度 
pUdphdr->checksum = 0;  //校验和,不是必需的 
char *pData = &buff[sizeof(IPHeader) + sizeof(UDPHeader)]; 
memcpy(pData, szMsg, nMsgLen); 
//填充校验和 
(pIphdr, pUdphdr, pData, nMsgLen); 
// 设置目的地址 
SOCKADDR_IN destAddr = { 0 }; 
destAddr.sin_family = AF_INET; 
destAddr.sin_port = htons(nDestPort); 
destAddr.sin_addr.S_un.S_addr = ::inet_addr(szDestIp); 
// 发送原始UDP封包 
int nRet; 
for(int i=0; i<5; i++) 
{ 
nRet = ::sendto(sRaw, buff, 
sizeof(IPHeader) + sizeof(UDPHeader) + nMsgLen, 0, (sockaddr*)&destAddr, sizeof(destAddr)); 
if(nRet == SOCKET_ERROR) 
{ 
printf(" sendto() failed: %d /n", ::WSAGetLastError()); 
break; 
} 
else 
{ 
printf(" sent %d bytes /n", nRet); 
} 
} 
::closesocket(sRaw); 
getchar(); 
return 0; 
} 
总结 
需要注意的是,如果这段代码在Windows XP SP2以前的操作系统上运行,可以使用假的源IP地址。但遗憾的是,Windows XP SP2中,则必须指定一个有效的IP地址,而且不是回环IP(即127.0.0.1)。Windows现在已经不支持原始TCP的发送了。这些种种限制,使得我们在XP上玩黑玩得很不自在!为了取消这种限制,我们可以开发自己的驱动,但开发驱动毕竟不是简单之事,我等菜鸟哪来这等本事啊。不过可喜的是,已经有高人为我们开发了一套当今非常流行的网络开发包驱动Winpcap,完全可以取消上面的限制!对于这种方法,我们以后再讨论,大家期待一下,呵呵