从网上载了一个程序,结果发现在WIN98下编译通过,但运行不出结果,测试后发现好像执行到recv()那里就再也不往下走了。但是把同样一个程序拿到WINXP里就可以显示出运行结果,可以把截获的IP包内容显示出来。请问,是不是WIN98不支持RAW SOCKET??还是其他什么原因??如何改进。
程序如下:
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>#define MAX_HOSTNAME_LAN 255
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
#define MAX_ADDR_LEN 16typedef struct tcpheader 
{
     unsigned short int sport;//信源端口
     unsigned short int dport;//信宿端口
     unsigned int th_seq;//序列号
     unsigned int th_ack;//确认号
     unsigned char th_x2:4;//
     unsigned char th_off:4;//数据偏移,长度为4位
     unsigned char Flags;//标志位
     unsigned short int th_win;//窗口域
     unsigned short int th_sum;//校验和
     unsigned short int th_urp;//紧急指针
}TCP_HDR;struct ipheader 
{
unsigned char ip_hl:4, ip_v:4; //IP头长度和IP版本号,各4位
unsigned char ip_tos;//服务类型
unsigned short int ip_len;//总长度
unsigned short int ip_id;//标识符
unsigned short int ip_off;//片偏移
unsigned char ip_ttl;//生存时间
unsigned char ip_p;//协议
unsigned short int ip_sum;//头校验和
unsigned int ip_src;//信源端口
unsigned int ip_dst;//信宿端口
}; typedef struct udphdr 
{
unsigned short sport;//信源端口
unsigned short dport;//信宿端口
unsigned short len;//总长度
unsigned short cksum;//校验和
}UDP_HDR;void main()
{
    SOCKET        sock;
    WSADATA       wsd;//wsd为指向WSADATA结构的指针
    char RecvBuf[65535] = {0};
DWORD  dwBytesRet;
int pCount=0;
unsigned int  optval = 1;
unsigned char *datatcp=NULL;
unsigned char *dataudp=NULL;
int lentcp=0, lenudp; WSAStartup(MAKEWORD(2,1),&wsd);//初始化WINSOCK
if((sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP))==SOCKET_ERROR)// 创建原始套接字
exit(1); char FAR name[MAX_HOSTNAME_LAN];
gethostname(name, MAX_HOSTNAME_LAN);//获取本机名

struct hostent FAR * pHostent;
pHostent = (struct hostent * )malloc(sizeof(struct hostent));
pHostent = gethostbyname(name);//获取给定主机名的IP地址

SOCKADDR_IN sa;
sa.sin_family = AF_INET;//填充SOCKADDR_IN结构
sa.sin_port = htons(6000);
memcpy(&sa.sin_addr.S_un.S_addr, pHostent->h_addr_list[0], pHostent->h_length); bind(sock, (SOCKADDR *)&sa, sizeof(sa));//将原始套接字绑定到本地网卡上
if ((WSAGetLastError())==10013)
exit(1); WSAIoctl(sock, SIO_RCVALL, &optval, sizeof(optval), NULL, 0, &dwBytesRet, NULL, NULL);
struct udphdr *pUdpheader;
struct ipheader *pIpheader;
struct tcpheader *pTcpheader;
char szSourceIP[MAX_ADDR_LEN], szDestIP[MAX_ADDR_LEN];
SOCKADDR_IN saSource, saDest;
pIpheader=(struct ipheader *)RecvBuf;//pIpheader指向IP包头部
pTcpheader=(struct tcpheader *)(RecvBuf+sizeof(struct ipheader));//pTcpheader指向TCP包头部
pUdpheader=(struct udphdr *)(RecvBuf+sizeof(struct ipheader));//pUdpheader指向UDP包头部
while(1)
{
memset(RecvBuf, 0, sizeof(RecvBuf));//*************************************************************
//下面这句recv()在WIN98下执行不了
//************************************************************* recv(sock, RecvBuf, sizeof(RecvBuf), 0);//从套接字接收数据 saSource.sin_addr.s_addr = pIpheader->ip_src;//信源端口
strncpy(szSourceIP, inet_ntoa(saSource.sin_addr), MAX_ADDR_LEN);//szSourceIP中放的是数据的信源IP地址,用点分十进制表示

saDest.sin_addr.s_addr = pIpheader->ip_dst;//信宿端口
strncpy(szDestIP, inet_ntoa(saDest.sin_addr), MAX_ADDR_LEN);//szDestIP中放的是数据的信宿IP地址,用点分十进制表示
        
lentcp =(ntohs(pIpheader->ip_len)-(sizeof(struct ipheader)+sizeof(struct tcpheader)));//TCP数据包长度=IP包总长度-IP头长度-TCP头长度
lenudp =(ntohs(pIpheader->ip_len)-(sizeof(struct ipheader)+sizeof(struct udphdr)));//UCP数据包长度=IP包总长度-IP头长度-UDP头长度

if((pIpheader->ip_p)==IPPROTO_TCP&&lentcp!=0)//若这个数据包采用的是TCP协议
{
printf("*******************************************\n");
pCount++;
datatcp=(unsigned char *)RecvBuf+sizeof(struct ipheader)+sizeof(struct tcpheader);
printf("-TCP-\n");
printf("\nDestination address->%s\n",szDestIP);//输出信宿IP地址
printf("\nDestination port->%i\n",ntohs(pTcpheader->dport));//输出信宿端口号
printf("datatcp address->%x\n",datatcp);
printf("size of ipheader->%i\n",sizeof(struct ipheader));//IP头部长度
printf("size of tcpheader->%i\n",sizeof(struct tcpheader));//TCP头部长度
printf("size of the whole packet->%i\n",ntohs(pIpheader->ip_len));//IP数据包的总长度
printf("\nchar Packet%i []=\"",pCount,lentcp);//pCount表示第几个包,lentcp表示这个tcp包的长度
for(int i=0;i<lentcp;i++)
{
printf("\\x%.2x",*(datatcp+i));//逐个输出包内的内容
//hexdump(datatcp+i);
if (i%10==0) //输出10个就换一行
{
printf("\"");
printf("\n\"");
}
}
printf("\";\n\n\n");//输出包内全部内容之后就空三行
for (int i2=0;i2<lentcp;i2++)
{
if(*(datatcp+i2)<=127&&*(datatcp+i2)>=0)
printf("%c",*(datatcp+i2));
else
printf("%d  ",*(datatcp+i2));
//printf(".");
//printf("%c",*(datatcp+i2));
}
printf("\n\n");
printf("*******************************************\n");
}
if( (pIpheader->ip_p)==IPPROTO_UDP&&lentcp!=0)
{
pCount++;
dataudp=(unsigned char *) RecvBuf+sizeof(struct ipheader)+sizeof(struct udphdr);
printf("-UDP-\n");
printf("\nDestination address->%s\n",szDestIP);
printf("\nDestination port->%d\n",ntohs(pTcpheader->dport));
printf("dataudp address->%x\n",dataudp);
printf("size of ipheader->%i\n",sizeof(struct ipheader));
printf("size of udpheader->%i\n",sizeof(struct udphdr));
printf("size of the hole packet->%i\n",ntohs(pIpheader->ip_len));
printf("\nchar Packet%i []=\"",pCount,lenudp);
for (int x=0;x<lenudp;x++)
{
printf("\\x%.2x",*(dataudp+x));
if (x%10==0) 
{
printf("\"");
printf("\n\"");
}
}
printf("\";\n\n\n");
for (int x2=0;x2<lenudp;x2++)
{
if( *(dataudp+x2)<=127&&*(dataudp+x2)>=0)
printf("%c",*(dataudp+x2));
else
printf(".");
}
printf("\n\n");
printf("*******************************************\n");
}
}
}
以上程序在WINXP中可以运行出结果,另注,要在工程中添加:WS2_32.LIB文件

解决方案 »

  1.   

    那怎么才能让98支持raw socket啊??
      

  2.   

    刚刚查了一下书——《windows网络编程》第二版,对于win95、win98和winnt4而言,如果用raw socket,只能使用igmp和icmp,楼主在程序中用到了udp和tcp,那么在95、98下是不行的了……
      

  3.   

    呵呵,楼主所言极是98不支持raw socket怎么也是不支持了-_-b
      

  4.   

    98下可以用winpcap来构造数据包
      

  5.   

    说错,98下可以用winpcap来捕获数据包
      

  6.   

    查了一篇文章,说是可以把NT下的某些模块移到98下,或者使用第三方工具,这样就可以使98系统支持raw socket,谁知道是哪些模块啊???又有哪些第三方工具呢?
      

  7.   

    98下不支持raw socket,因为raw socket选项在2000下根本不支持,你要在98下使用,必须使用别的抓包工具,比如winpcap
      

  8.   

    98下不支持raw socket,你要在98下使用,必须使用别的抓包工具,比如winpcap
      

  9.   

    嗯,楼主直接用winpcap得了,哪个系统都能用