需要帮助使用Windows套接字来查看所有传入的数据包

时间:2014-04-29 15:52:14

标签: c++ windows visual-studio-2010 sockets networking

我正在尝试创建一个程序,可以接收并显示所有传入的数据包到我的家庭网络。这只是一个有趣的'项目,因为我试图更好地使用计算机网络。

我找到了几个关于使用套接字的教程,我试图模仿他们正在做的事情。 (目前使用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表示无效参数。

所以我想,&#34;好吧,我想我应该传递正确的类型,而不是试图强制将错误类型转换为正确的类型。&#34;

然后我创建了一个变量

LPDWORD rett = new DWORD;

这样做,我编译成功,但我再次收到错误代码10022。

此时,我不知道还能做什么。有人可以帮助我让这个程序工作吗?

1 个答案:

答案 0 :(得分:0)

尝试更像这样的事情:

#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;
    int a = WSAStartup( MAKEWORD(2,2), &WsaData);
    if (a != 0)
    {
        printf("WSAStartup() failed. Error %d\n", a);
        return false;
    }
#endif
    return true;
}

void ShutdownSockets()
{
#if PLATFORM == PLATFORM_WINDOWS
    WSACleanup();
#endif
}

#if PLATFORM != PLATFORM_WINDOWS
void closesocket(int socket)
{
    close(socket);
}
#endif

int GetLastSocketError()
{
#if PLATFORM == PLATFORM_WINDOWS
    return WSAGetLastError();
#else
    return errno;
#endif
}

int main()
{
    if (!InitializeSockets())
        return -1;

    int thisSocket = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
    if (thisSocket == -1)
    {
        printf("socket() failed. Error %d\n", GetLastSocketError());
        ShutdownSockets();
        return -1;
    }

    sockaddr_in bindaddr = {0};
    bindaddr.sin_family = AF_INET;
    // set bindaddr.sin_addr.s_addr to the desired local IP that you want to sniff from...

    if (bind(thisSocket, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) == -1)
    {
        printf("bind() failed. Error %d\n", GetLastSocketError());
        closesocket(thisSocket);
        ShutdownSockets();
        return -1;
    }

    u_long optVal = 1;
    if (setsockopt(thisSocket, IPPROTO_IP, IP_HDRINCL, (char *)&optVal, sizeof(optVal)) == -1)
    {
        printf("setsockopt() failed. Error %d\n", GetLastSocketError());
        closesocket(thisSocket);
        ShutdownSockets();
        return -1;
    }

#if PLATFORM == PLATFORM_WINDOWS    
    DWORD inn = RCVALL_ON;
    if (WSAIoctl(thisSocket, SIO_RCVALL, &inn, sizeof(inn), NULL, 0, NULL, NULL, NULL) == -1)
    {
        printf("WSAIoctl() failed. Error %d\n", GetLastSocketError());
        closesocket(thisSocket);
        ShutdownSockets();
        return -1;
    }
#endif

    u_char Buffer[0xffff];

    while(1)
    {
        int len = recvfrom(thisSocket, (char*)Buffer, sizeof(Buffer), NULL, 0, 0);
        if (len == -1)
        {
            printf("recvfrom() failed. Error %d\n", GetLastSocketError());
            closesocket(thisSocket);
            ShutdownSockets();
            return -1;
        }

        printIpPacket(Buffer, len);
    }

    closesocket(thisSocket);
    ShutdownSockets();

    return 0;
}