【发布时间】:2014-04-29 15:52:13
【问题描述】:
我正在尝试创建一个程序,该程序可以接收和显示所有传入家庭网络的数据包。这只是一个“好玩”的项目,因为我正在努力更好地使用计算机网络。
我找到了一些关于使用套接字的教程,我正在尝试模仿他们正在做的事情。 (目前正在使用this(初始化内容来自this)教程)。
但是,我在使代码正常工作时遇到了一些问题。这是我到目前为止的代码:(因为我知道我只会在 windows 上使用它,所以我只是省略了 mac 和 unix 的其他 marcos)
#define PLATFORM_WINDOWS 1
#if defined(_WIN32)
#define PLATFORM PLATFORM_WINDOWS
#endif
#if PLATFORM == PLATFORM_WINDOWS
#include <WinSock2.h>
#endif
#pragma comment( lib, "wsock32.lib" );
#pragma comment( lib, "Ws2_32.lib" );
#include <iostream>
bool InitializeSockets()
{
#if PLATFORM == PLATFORM_WINDOWS
WSADATA WsaData;
return WSAStartup( MAKEWORD(2,2), &WsaData);
#else
return true;
#endif
}
void ShutdownSockets()
{
#if PLATFORM == PLATFORM_WINDOWS
WSACleanup();
#endif
}
void printIpPacket(unsigned char* data, int length)
{
printf("-----------------Packet Begins-----------------\n");
printf("IP Version: %i, Packet Size: %ibytes, Id: %i\n",
(data[0]>>4), (data[2]*256)+data[3], (data[4]*256)+data[5]);
printf("Fragment: %i, TTL: %i, HL: %iwds, Protocol: %i\n",
((int)(data[6]>>4)*256)+data[7], data[8], ((char)(data[0]<<4))>>4, data[9]);
printf("Source: %i.%i.%i.%i, Destination: %i.%i.%i.%i\n",
data[12], data[13], data[14], data[15],
data[16], data[17], data[18], data[19]);
//the data inside the packet starts at --> data+(((char)(data[0]<<4))>>2)
//new data length --> length-(((char)(data[0]<<4))>>2)
//continue printing the rest of the headers :o
printf("\n------------------Packet Ends------------------\n");
}
int main()
{
InitializeSockets();
int thisSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
int optVal = 1;
setsockopt(thisSocket, IPPROTO_IP, 2, (char *)&optVal, sizeof(optVal));
int inn = 1, outt;
long rett;
int err = WSAIoctl(thisSocket, 0x98000001, &inn, sizeof(inn), &outt, sizeof(outt), &rett, 0, 0);
int a = WSAGetLastError();
}
我在使WSAIoctl 函数工作时遇到了一些问题。本教程声称可以工作的代码甚至无法编译。我得到了错误:
error C2664: 'WSAIoctl' : cannot convert parameter 7 from 'long *' to 'LPDWORD'
然后,我将 WSAIoctl 函数行更改为:
int err = WSAIoctl(thisSocket, 0x98000001, &inn, sizeof(inn), &outt, sizeof(outt), (LPDWORD)&rett, 0, 0);
这已编译,但随后 WSAGetLastError() 返回错误代码 10022,根据 this 表示无效参数。
然后我想,“好吧,与其试图强制将错误的类型转换为正确的类型,我想我应该只传递正确的类型。”
然后我创建了一个变量
LPDWORD rett = new DWORD;
这样做,我编译成功,但我再次收到错误代码 10022。
在这一点上,我不知道还能做什么。有人可以帮我让这个程序运行吗?
【问题讨论】:
-
关于你的变量,改变 variable 的类型有什么问题吗? :
DWORD rett = 0;,然后像以前一样通过&rett?关于你的错误。关于您的错误,如果您要使用SIO_RCVALL嗅探数据包,则套接字应该是SOCK_RAW,而不是SOCK_STREAM。我意识到documentation for WSAIoctl 很广泛,但功能本身的力量也是如此。拥有强大的力量......无论如何,祝你好运。 -
所以我创建了 DWORD 并按照您所说的传递了它的地址,现在我收到错误代码 10038:
Socket operation on nonsocket. An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket, or for select, a member of an fd_set was not valid. -
确保
thisSocket创建成功。我想你使用了 SOCK_RAW。您需要提升权限才能执行此操作。 -
@user58697 啊,检查套接字创建的错误,我收到错误 10013,意味着我没有正确设置权限。我的机器上当前没有运行任何防病毒/防火墙。还有什么我可以尝试解决的吗?
-
@xcdemon05:你需要使用
SOCK_RAW来进行数据包捕获,但是正如user58697所说,SOCK_RAW需要管理员权限,并且是documented这样:“原始套接字提供了以下能力操纵底层传输,因此它们可用于构成安全威胁的恶意目的。因此,只有管理员组的成员才能在 Windows 2000 及更高版本上创建 SOCK_RAW 类型的套接字。
标签: c++ windows visual-studio-2010 sockets networking