MFC Application getting stuck when adding list control elements [closed]

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-12 02:46:35

问题


MFC application getting stuck when adding elements into list control unable to click anyother button or even close button when sniffing network packets.

The Whole code is as shown below:

// SnifferSampleDlg.cpp : implementation file
//

#include "stdafx.h"
#include "SnifferSample.h"
#include "SnifferSampleDlg.h"
#include "afxdialogex.h"
#include <Windows.h>
#include <WinSock2.h>
#include <mstcpip.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#pragma comment(lib,"ws2_32.lib") //For winsock

// CSnifferSampleDlg dialog


//typedef struct ip_hdr
//{
//  unsigned char ip_header_len:4; // 4-bit header length (in 32-bit words) normally=5 (Means 20 Bytes`enter code here` may be 24 also)
//  unsigned char ip_version :4; // 4-bit IPv4 version
//  unsigned char ip_tos; // IP type of service
//  unsigned short ip_total_length; // Total length
//  unsigned short ip_id; // Unique identifier
//
//  unsigned char ip_frag_offset :5; // Fragment offset field
//
//  unsigned char ip_more_fragment :1;
//  unsigned char ip_dont_fragment :1;
//  unsigned char ip_reserved_zero :1;
//
//  unsigned char ip_frag_offset1; //fragment offset
//
//  unsigned char ip_ttl; // Time to live
//  unsigned char ip_protocol; // Protocol(TCP,UDP etc)
//  unsigned short ip_checksum; // IP checksum
//  unsigned int ip_srcaddr; // Source address
//  unsigned int ip_destaddr; //destination address
//} IPV4_HDR;

typedef struct tcp_header
{
    unsigned short source_port; // source port
    unsigned short dest_port; // destination port
    unsigned int sequence; // sequence number - 32 bits
    unsigned int acknowledge; // acknowledgement number - 32 bits

    unsigned char ns :1; //Nonce Sum Flag Added in RFC 3540.
    unsigned char reserved_part1:3; //according to rfc
    unsigned char data_offset:4; /*The number of 32-bit words in the TCP header.
    This indicates where the data begins.
    The length of the TCP header is always a multiple
    of 32 bits.*/

    unsigned char fin :1; //Finish Flag
    unsigned char syn :1; //Synchronise Flag
    unsigned char rst :1; //Reset Flag
    unsigned char psh :1; //Push Flag
    unsigned char ack :1; //Acknowledgement Flag
    unsigned char urg :1; //Urgent Flag

    unsigned char ecn :1; //ECN-Echo Flag
    unsigned char cwr :1; //Congestion Window Reduced Flag

    ////////////////////////////////

    unsigned short window; // window
    unsigned short checksum; // checksum
    unsigned short urgent_pointer; // urgent pointer
} TCP_HDR;

int total = 0,icmp = 0, igmp = 0,tcp = 0 ,udp = 0 ,others = 0;

CSnifferSampleDlg::CSnifferSampleDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(CSnifferSampleDlg::IDD, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CSnifferSampleDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_LIST1, m_listCtrl);
}

BEGIN_MESSAGE_MAP(CSnifferSampleDlg, CDialogEx)
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_BUTTON1, &CSnifferSampleDlg::OnBnClickedButton1)
END_MESSAGE_MAP()


// CSnifferSampleDlg message handlers
static void AddData(CListCtrl &ctrl, int row, int col, LPWSTR str)
{
    LVITEM lv;
    lv.iItem = row;
    lv.iSubItem = col;
    lv.pszText =  str;
    lv.mask = LVIF_TEXT;


    if(col == 0)
        ctrl.InsertItem(0,str);
        /*ctrl.RedrawItems(  0,   tcp);*/
    else
        ctrl.SetItem(&lv);  
}

BOOL CSnifferSampleDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);         // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon

    // TODO: Add extra initialization here

    m_listCtrl.InsertColumn(0, L"Source");
    m_listCtrl.SetColumnWidth(0, 100);

    m_listCtrl.InsertColumn(1,L"Destination");
    m_listCtrl.SetColumnWidth(1, 100);

    m_listCtrl.InsertColumn(2, L"Protocol");
    m_listCtrl.SetColumnWidth(2, 90);

    m_listCtrl.SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, 0,   
    LVS_EX_FULLROWSELECT);

    return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CSnifferSampleDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialogEx::OnPaint();
    }
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CSnifferSampleDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}

int CSnifferSampleDlg::Startbutton()
{
    SOCKET ListenSocket;
    struct sockaddr_in saServer;
    hostent* localHost;
    char* localIP;
    WSADATA wsaData;
    int iResult;
    tcp=0;
    //Initialising Winsock....
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0)
    {
        AfxMessageBox(L"WSAStartup() failed");
        return 1;
    }
    //Creating RAW socket for listening 
    ListenSocket = socket (AF_INET,SOCK_RAW,IPPROTO_IP);

    localHost = gethostbyname("");
    localIP = inet_ntoa (*(struct in_addr *)*localHost->h_addr_list);

    saServer.sin_family = AF_INET;
    saServer.sin_addr.s_addr = inet_addr(localIP);
    saServer.sin_port = htons(5150);

// Bind the listening socket using the
// information in the sockaddr structure
    iResult = bind( ListenSocket,(SOCKADDR*) &saServer, sizeof(saServer) );
    if( iResult != 0){
        AfxMessageBox(L"Binding the address with the socket failed "); 
        return 1;
    }

    AfxMessageBox(L"Binding successful");
    int in_buffer=1, out_buffer;
    if (WSAIoctl(ListenSocket,SIO_RCVALL, &in_buffer,sizeof(in_buffer), 0, 0,(LPDWORD) &out_buffer , 0 , 0) == SOCKET_ERROR)
    {
        AfxMessageBox(L"WSAIoctl() failed...");
        return 1;
    }
    AfxMessageBox(L"Socket Set");
    CString strText;
int nColumnCount = m_listCtrl.GetHeaderCtrl()->GetItemCount();

    StartSniffing(ListenSocket);
    closesocket(ListenSocket);
    WSACleanup();
    return 0;
}
void CSnifferSampleDlg::StartSniffing(SOCKET sniffer){
    char *Buffer = (char *)malloc(65536); 
    int mangobyte;

    if (Buffer == NULL)
    {
        printf("malloc() failed.\n");
        return;
    }

    do
    {
        mangobyte = recvfrom(sniffer , Buffer , 65536 , 0 , 0 , 0);

        if(mangobyte > 0)
        {
            ProcessPacket(Buffer,mangobyte);
            /*if(tcp==50)
                break;*/
        }
        else
        {
            printf( "recvfrom() failed.\n");
        }
    }
    while (mangobyte > 0);

    free(Buffer);
}
void CSnifferSampleDlg::ProcessPacket(char* buffer,int size){
    ip.ValueAssign(buffer);
    ++total;

 //Check the Protocol and do accordingly...
    switch (ip.ip_protocol)
    {
        case 1: //ICMP Protocol
        ++icmp;
        break;

        case 2: //IGMP Protocol
        ++igmp;
        break;

        case 6: //TCP Protocol
        ++tcp;
        ProcessTCPPacket(buffer,size);
        /*if(tcp==50)
            break;*/
        break;

        case 17: //UDP Protocol
        ++udp;
        break;

        default: //Some Other Protocol like ARP etc.
        ++others;
        break;
    }
    printf("TCP : %d UDP : %d ICMP : %d IGMP : %d Others : %d Total : %d\r",tcp,udp,icmp,igmp,others,total);
}
void CSnifferSampleDlg::ProcessTCPPacket(char* buffer,int size){
    unsigned short iphdrlen;
    SOCKADDR_IN source;
    char* source_addr;
    char* destination_addr;

    source.sin_addr.s_addr = ip.ip_srcaddr;
    source_addr=inet_ntoa(source.sin_addr);

    SOCKADDR_IN destination;
    wchar_t source_address[20];
    wchar_t destination_address[20];
    mbstowcs_s(0,source_address,source_addr,strlen(source_addr)+1); //method used to convert char* to LPWSTR
    destination.sin_addr.s_addr = ip.ip_destaddr;
    destination_addr=inet_ntoa(destination.sin_addr);
    mbstowcs_s(0,destination_address,destination_addr,strlen(destination_addr)+1);
    m_listCtrl.InsertColumn(3,L"");
    m_listCtrl.SetColumnWidth(3, 80);
    m_listCtrl.SetRedraw(FALSE);
    AddData(m_listCtrl,0,0,source_address);
    /*AddData(m_listCtrl,0,1,destination_address);
    AddData(m_listCtrl,0,2,L"TCP");*/
    m_listCtrl.SetRedraw(TRUE);
    m_listCtrl.DeleteColumn(3);
}
void CSnifferSampleDlg::OnBnClickedButton1()
{
    Startbutton();
}

Even when I used threading it is not working fine.

Packet sniffing is actually a continues process until a stop button is pressed. But here in this program when sniffing is done no other buttons are able to be pressed, the application getting stuck. When I restrict the sniffing to say 20 or 50 then after that much packet only we can do anything else. But restricting the application to 20 or 50 packets is a big disadvantage.


回答1:


  1. First of all you should definitely put your socket-based packet listener and parser into a thread. The main thread is dedicated for GUI tasks only.

  2. You need to enable virtual mode for your list control. In this mode, the list view control doesn't host any data itself. All it knows is rows that should be currently displayed. The actual data is requested on demand. That makes your application responsible for managing the data it displays.

  3. Find out more at: https://msdn.microsoft.com/en-us/library/ye4z8x58.aspx

Here is short example on how to use it:

You need to set the number of items in the list control. The list thinks it has this number of items even though we have not added anything:

The m_DataArray is defined as CArray<CDataItemInfo> m_DataArray;

m_DataListCtrl.SetItemCountEx((int)m_DataArray.GetSize(),
     LVSICF_NOSCROLL|LVSICF_NOINVALIDATEALL);

...

BEGIN_MESSAGE_MAP(CListCtrlTestDlg, CDialog)
    ON_NOTIFY(LVN_GETDISPINFO, IDC_DATA_LIST, OnGetDispInfoList)
END_MESSAGE_MAP()

void CListCtrlTestDlg::OnGetDispInfoList(NMHDR* pNMHDR, LRESULT* pResult) 
{
    NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);

    LV_ITEM& LstItem = pDispInfo->item;

    int nItem = LstItem.iItem;

    if(nItem > m_DataArray.GetSize()-1)
        return; 

    const CDataItemInfo& ItemData = m_DataArray[nItem];

    if (LstItem.mask & LVIF_TEXT) 
    {
        //Copy the text to the LV_ITEM structure
        //Maximum number of characters is in LstItem.cchTextMax
        lstrcpyn(LstItem.pszText, ItemData.GetColumnText(LstItem.iSubItem), LstItem.cchTextMax);
    }

}


来源:https://stackoverflow.com/questions/33411941/mfc-application-getting-stuck-when-adding-list-control-elements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!