Click here to Skip to main content
15,905,915 members
Home / Discussions / C / C++ / MFC
   

C / C++ / MFC

 
GeneralRe: Overlapped IO sockets sending and receiving at the same time Pin
Richard Andrew x6416-Nov-11 12:50
professionalRichard Andrew x6416-Nov-11 12:50 
QuestionCSimpleDate and Visual Studio 2010 Pin
xyloweb16-Nov-11 4:39
xyloweb16-Nov-11 4:39 
AnswerRe: CSimpleDate and Visual Studio 2010 Pin
Chris Losinger16-Nov-11 4:54
professionalChris Losinger16-Nov-11 4:54 
SuggestionRe: CSimpleDate and Visual Studio 2010 Pin
David Crow16-Nov-11 5:03
David Crow16-Nov-11 5:03 
AnswerRe: CSimpleDate and Visual Studio 2010 Pin
Maximilien16-Nov-11 8:59
Maximilien16-Nov-11 8:59 
AnswerRe: CSimpleDate and Visual Studio 2010 Pin
xyloweb25-Nov-11 9:09
xyloweb25-Nov-11 9:09 
SuggestionCollaborated Tool/Library development Pin
BrainlessLabs.com15-Nov-11 22:59
BrainlessLabs.com15-Nov-11 22:59 
GeneralRe: Collaborated Tool/Library development Pin
Richard MacCutchan15-Nov-11 23:51
mveRichard MacCutchan15-Nov-11 23:51 
GeneralRe: Collaborated Tool/Library development Pin
BrainlessLabs.com16-Nov-11 6:53
BrainlessLabs.com16-Nov-11 6:53 
QuestionEnumerating Registry Subkeys c++ Pin
Member 824522215-Nov-11 20:06
Member 824522215-Nov-11 20:06 
AnswerRe: Enumerating Registry Subkeys c++ Pin
Richard MacCutchan15-Nov-11 22:09
mveRichard MacCutchan15-Nov-11 22:09 
AnswerRe: Enumerating Registry Subkeys c++ Pin
User 742933815-Nov-11 22:14
professionalUser 742933815-Nov-11 22:14 
GeneralRe: Enumerating Registry Subkeys c++ Pin
Richard MacCutchan15-Nov-11 23:55
mveRichard MacCutchan15-Nov-11 23:55 
Questionsimple static library linking to dll issue. Pin
Android Lava15-Nov-11 16:32
Android Lava15-Nov-11 16:32 
AnswerRe: simple static library linking to dll issue. Pin
Richard MacCutchan15-Nov-11 22:04
mveRichard MacCutchan15-Nov-11 22:04 
AnswerRe: simple static library linking to dll issue. Pin
Chuck O'Toole16-Nov-11 5:41
Chuck O'Toole16-Nov-11 5:41 
AnswerRe: simple static library linking to dll issue. Pin
jschell16-Nov-11 10:00
jschell16-Nov-11 10:00 
QuestionURLDownloadToFile, Cancel Button Pin
jkirkerx15-Nov-11 15:09
professionaljkirkerx15-Nov-11 15:09 
AnswerRe: URLDownloadToFile, Cancel Button Pin
Chuck O'Toole15-Nov-11 16:19
Chuck O'Toole15-Nov-11 16:19 
GeneralRe: URLDownloadToFile, Cancel Button Pin
jkirkerx15-Nov-11 16:32
professionaljkirkerx15-Nov-11 16:32 
AnswerRe: URLDownloadToFile, Cancel Button Pin
Chuck O'Toole15-Nov-11 17:01
Chuck O'Toole15-Nov-11 17:01 
GeneralRe: URLDownloadToFile, Cancel Button Pin
jkirkerx15-Nov-11 17:19
professionaljkirkerx15-Nov-11 17:19 
GeneralRe: URLDownloadToFile, Cancel Button Pin
jkirkerx16-Nov-11 11:01
professionaljkirkerx16-Nov-11 11:01 
GeneralRe: URLDownloadToFile, Cancel Button Pin
enhzflep16-Nov-11 13:40
enhzflep16-Nov-11 13:40 
They're both a lot easier having done them than before. I had no idea about threads or sockets 2 1/2 weeks ago, but have now learnt enough to get by and have cobbled together a rss reader - one which can pre-load all subscribed feeds in parallel, each in it's own thread.

Notifying the main window of a thread's completion is the easier of the two. Without MFC, it's as (1) defining a user message, and deciding on the format (if any) of the passed information (2) sending that message to the main window upon completion (3) handling that message in the main window.

E.g
Part 1 - Main window completion notification mechanism
C++
#define WM_GALLERY_HTML_AVAILABLE WM_USER+1
#define WM_FILE_DOWNLOAD_COMPLETE WM_USER+2
...
...
...
__stdcall void galleryHtmlDownloadedCallbackFunc(PVOID data)
{
    downloadHeader_t *hdr;
    hdr = (downloadHeader_t*)data;

    galHtmlStr = hdr->result;
    galUrlStr = hdr->szUrl;

    free(hdr->result);
    hdr->result = NULL;
    hdr->contentLen = 0;

    PostMessage(mainDlgWnd, WM_GALLERY_HTML_AVAILABLE, 0, 0);
}

...
...
...
...

    case WM_INITDIALOG:
        mainDlgWnd = hwndDlg;
        editWnd = GetDlgItem(hwndDlg, IDC_RICHEDIT1);
        SetFocus(GetDlgItem(hwndDlg, IDC_RICHEDIT1));
        return FALSE;

    case WM_FILE_DOWNLOAD_COMPLETE:
        return true;

    case WM_GALLERY_HTML_AVAILABLE:
        findLinks((char*)galHtmlStr.c_str(), links, validExts);
        strLinks.clear();
        printf("Number of links: %d\n", links.size());
        for (i=0; i<links.size(); i++)
            strLinks += links[i] + "\n";
        SetDlgItemText(mainDlgWnd, IDC_RICHEDIT1, strLinks.c_str());
        return true;

    case WM_CLOSE:
        EndDialog(hwndDlg, 0);
        return TRUE;


Part 2 - Threading mechanism


C++
///////// usage example single (extra) thread //////////

    static downloadHeader_t curDownload;
    GetWindowText(urlHwnd, szUrl, urlLen+1);
    savePath = getFolderName(mainDlgWnd, "C:\\001");

    if (strlen(szUrl) && strlen(savePath))
    {
        curDownload.szUrl = szUrl;
        curDownload.callback = (voidFuncPtr)galleryHtmlDownloadedCallbackFunc;
        curDownload.saveFilePath = savePath;
        _beginthread(DownloadThread, NULL, (void*)&(curDownload));
    }

    delete savePath;
    delete szUrl;

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


typedef void (*voidFuncPtr)(void*);
struct downloadHeader_t
{
    string szUrl;             // in
    voidFuncPtr callback;     // in
    string saveFilePath;     // in
    PVOID lParam;             // in

    SOCKET conn;
    char *readBuffer, *sendBuffer, *tmpBuffer, *result;
    string server, filepath, filename;
    long thisReadSize, headerLen, contentLen;
};


// seperate a url into it's components
void mParseUrl(char *mUrl, string &serverName, string &filepath, string &filename)
{
    string::size_type n;
    string url = mUrl;

    if (url.substr(0,7) == "http://")
        url.erase(0,7);

    n = url.find('/');
    if (n != string::npos)
    {
        serverName = url.substr(0,n);
        filepath = url.substr(n);
        n = filepath.rfind('/');
        filename = filepath.substr(n+1);
    }

    else
    {
        serverName = url;
        filepath = "/";
        filename = "";
    }
}


// return the socket number for a TCP connection
SOCKET connectToServer(char *szServerName, WORD portNum)
{
    struct hostent *hp;
    unsigned int addr;
    struct sockaddr_in server;
    SOCKET conn;
//SOCKHANDLE_USE_OVERLAPPED
    conn = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (conn == INVALID_SOCKET)
        return NULL;

    if(inet_addr(szServerName)==INADDR_NONE)
    {
        hp=gethostbyname(szServerName);
    }
    else
    {
        addr=inet_addr(szServerName);
        hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);
    }

    if(hp==NULL)
    {
        closesocket(conn);
        return NULL;
    }

    server.sin_addr.s_addr=*((unsigned long*)hp->h_addr);
    server.sin_family=AF_INET;
    server.sin_port=htons(portNum);
    if(connect(conn,(struct sockaddr*)&server,sizeof(server)))
    {
        closesocket(conn);
        return NULL;
    }
    return conn;
}

// searches the content returned from a server for 2 newlines in a row - this signifies the end of the header.
// the RFC (I forget the number) states that "\r\n\r\n" to be the valid terminator, however not all sites conform
// to the standard.
int getHeaderLength(char *content)
{
    const char *srchStr1 = "\r\n\r\n", *srchStr2 = "\n\r\n\r";
    char *findPos;
    int ofset = -1;

    findPos = strstr(content, srchStr1);
    if (findPos != NULL)
    {
        ofset = findPos - content;
        ofset += strlen(srchStr1);
    }

    else
    {
        findPos = strstr(content, srchStr2);
        if (findPos != NULL)
        {
            ofset = findPos - content;
            ofset += strlen(srchStr2);
        }
    }
    return ofset;
}






/*
struct downloadHeader_t
{
    string szUrl;            // in
    voidFuncPtr callback;     // in
    channelDef_t *channel;  // in

    SOCKET conn;
    char *readBuffer, *sendBuffer, *tmpBuffer, *result;
    string server, filepath, filename;
    long thisReadSize, headerLen, contentLen;
};
*/
void __stdcall DownloadThread(void *dat)
{
    downloadHeader_t *hdr;
    hdr = (downloadHeader_t *)dat;
    const int bufSize = 512;

    printf("download thread - \n");

    hdr->result = NULL;
    hdr->readBuffer = (char*)malloc(bufSize);
    hdr->sendBuffer = (char*)malloc(bufSize);
    hdr->tmpBuffer = (char*)malloc(bufSize);

    printf("download thread - \n");

    mParseUrl((char*)hdr->szUrl.c_str(), hdr->server, hdr->filepath, hdr->filename);

    printf("download thread - \n");
//http://forums.devshed.com/c-programming-42/any-ideas-863939.html
    ///////////// step 1, connect //////////////////////
//    printf("connecting to %s\n", hdr->server.c_str());
    hdr->conn = connectToServer((char*)hdr->server.c_str(), 80);
    if (hdr->conn)
        printf("download thread - connected?\n");

    ///////////// step 2, send GET request /////////////
    sprintf(hdr->tmpBuffer, "GET %s HTTP/1.0", hdr->filepath.c_str());
    strcpy(hdr->sendBuffer, hdr->tmpBuffer);
    strcat(hdr->sendBuffer, "\r\n");
    sprintf(hdr->tmpBuffer, "Host: %s", hdr->server.c_str());
    strcat(hdr->sendBuffer, hdr->tmpBuffer);
    strcat(hdr->sendBuffer, "\r\n");
    strcat(hdr->sendBuffer, "\r\n");
//    printf("sending:\n'%s'", hdr->sendBuffer);
    send(hdr->conn, hdr->sendBuffer, strlen(hdr->sendBuffer), 0);

    ///////////// step 3 - get received bytes ////////////////
    // Receive until the peer closes the connection
    hdr->contentLen = 0;
    while(1)
    {
        memset(hdr->readBuffer, 0, bufSize);
        hdr->thisReadSize = recv (hdr->conn, hdr->readBuffer, bufSize, 0);
        if ( hdr->thisReadSize <= 0 )
            break;

        // nasty - but seemingly necessary. Headers don't always include the content-length
        // without a known content length, we cannot accurately allocate the memory required to hold
        // the full (header+message) response. Therefore, we re-allocate our memory each time a successful read is performed.
        // the alternative would be to write directly to file, or allocate (hopefully) more memory than we
        // need (Too bad if we allocate 10 Mb & a resource is 10.1 Mb !)
        hdr->result = (char*)realloc(hdr->result, hdr->thisReadSize+hdr->contentLen);

        memcpy(hdr->result+hdr->contentLen, hdr->readBuffer, hdr->thisReadSize);
        hdr->contentLen += hdr->thisReadSize;
    }

    hdr->headerLen = getHeaderLength(hdr->result);
    hdr->contentLen -= hdr->headerLen;
    memmove(hdr->result, hdr->result+hdr->headerLen, hdr->contentLen);
    realloc(hdr->result, hdr->contentLen+1);
    hdr->result[hdr->contentLen] = 0x0;
    closesocket(hdr->conn);
    free(hdr->readBuffer);
    free(hdr->sendBuffer);
    free(hdr->tmpBuffer);

    if (hdr->callback)
        hdr->callback(hdr);
}

GeneralRe: URLDownloadToFile, Cancel Button Pin
jkirkerx17-Nov-11 6:15
professionaljkirkerx17-Nov-11 6:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.