<windows网络编程>第9章有完整的例子。关键是用WSAIoctl()设置SIO_RCVALL    // Create a raw socket for receiving IP datagrams
    //
    s = WSASocket(AF_INET, SOCK_RAW, dwProtocol, NULL, 0, WSA_FLAG_OVERLAPPED);
    if (s == INVALID_SOCKET)
    {
        printf("WSASocket() failed: %d\n", WSAGetLastError());
        return -1;
    }
    // Get an interface to read IP packets on
    //
    if (GetInterface(s, &if0, dwInterface) != 0)
    {
        printf("Unable to obtain an interface\n");
        return -1;
    }
    printf("Binding to IF: %s\n", inet_ntoa(if0.sin_addr));
    //
    // This socket must be bound before calling the ioctl
    //
    if0.sin_family = AF_INET;
    if0.sin_port = htons(0);    if (bind(s, (SOCKADDR *)&if0, sizeof(if0)) == SOCKET_ERROR)
    {
        printf("bind() failed: %d\n", WSAGetLastError());
        return -1;
    }
    //
    // Set the SIO_RCVALLxxx ioctl
    //
    optval = 1;
    if (WSAIoctl(s, dwIoControlCode, &optval, sizeof(optval),
            NULL, 0, &dwBytesRet, NULL, NULL) == SOCKET_ERROR)
    {
        printf("WSAIotcl(%d) failed; %d\n", dwIoControlCode,
            WSAGetLastError());
        return -1;
    }
    // Start receiving IP datagrams until interrupted
    // 
    count = 0;
    while (1)
    {
        wbuf.len = MAX_IP_SIZE;
        wbuf.buf = rcvbuf;
        dwFlags  = 0;        ret = WSARecv(s, &wbuf, 1, &dwBytesRet, &dwFlags, NULL, NULL);
        if (ret == SOCKET_ERROR)
        {
            printf("WSARecv() failed: %d\n", WSAGetLastError());
            return -1;
        }
        // Decode the IP header
        //
        if (!(nproc = DecodeIPHeader(&wbuf, uiSourceAddr, usSourcePort,
                uiDestAddr, usDestPort)))
        {
            printf("Error decoding IP header!\n");
            break;
        }
    }
    // Cleanup
    //
    closesocket(s);
    WSACleanup();
    return 0;