C++獲取URL內容

原文鏈接:https://stackoverflow.com/questions/1011339/how-do-you-make-a-http-request-with-c

CSDN上面的文章是真的垃圾,找個能用的訪問URL的代碼真的是難。大部分人都是相互抄抄抄,還抄不全,代碼不可用,什麼鬼博客。一點幫助都沒有,浪費時間,浪費生命。

以下內容摘自StackOverFlow 鏈接

#ifndef HTTPUTIL_H
#define HTTPUTIL_H
#include <windows.h>
#include <string>
#include <stdio.h>

using std::string;

#pragma comment(lib,"ws2_32.lib")


void mParseUrl(char *mUrl, string &serverName, string &filepath, string &filename);
SOCKET connectToServer(char *szServerName, WORD portNum);
int getHeaderLength(char *content);
char *readUrl2(char *szUrl, long &bytesReturnedOut, char **headerOut);


char *sendRequest(char szUrl[]) {
    WSADATA wsaData;
    //char szUrl[] = "http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp";
    long fileSize;
    char *memBuffer, *headerBuffer;

    memBuffer = headerBuffer = nullptr;

    if (WSAStartup(0x101, &wsaData) != 0)
        return nullptr;

    memBuffer = readUrl2(szUrl, fileSize, &headerBuffer);
    printf("returned from readUrl\n");
    printf("data returned:\n%s", memBuffer);
    if (fileSize != 0) {
        //delete (memBuffer);
        delete (headerBuffer);
    }
    WSACleanup();
    return memBuffer;
}

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);

    if (url.substr(0, 8) == "https://")
        url.erase(0, 8);

    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 = "";
    }
}

SOCKET connectToServer(char *szServerName, WORD portNum) {
    struct hostent *hp;
    unsigned int addr;
    struct sockaddr_in server;
    SOCKET conn;

    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 == nullptr) {
        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;
}

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 != nullptr) {
        ofset = findPos - content;
        ofset += strlen(srchStr1);
    }

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

char *readUrl2(char *szUrl, long &bytesReturnedOut, char **headerOut) {
    const int bufSize = 512;
    char readBuffer[bufSize], sendBuffer[bufSize], tmpBuffer[bufSize];
    char *tmpResult = nullptr, *result;
    SOCKET conn;
    string server, filepath, filename;
    long totalBytesRead, thisReadSize, headerLen;

    mParseUrl(szUrl, server, filepath, filename);

    ///////////// step 1, connect //////////////////////
    conn = connectToServer((char *)server.c_str(), 80);

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

    //    SetWindowText(edit3Hwnd, sendBuffer);
    printf("Buffer being sent:\n%s", sendBuffer);

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

        if ( thisReadSize <= 0 )
            break;

        tmpResult = (char *)realloc(tmpResult, thisReadSize + totalBytesRead);

        memcpy(tmpResult + totalBytesRead, readBuffer, thisReadSize);
        totalBytesRead += thisReadSize;
    }

    headerLen = getHeaderLength(tmpResult);
    long contenLen = totalBytesRead - headerLen;
    result = new char[contenLen + 1];
    memcpy(result, tmpResult + headerLen, contenLen);
    result[contenLen] = 0x0;
    char *myTmp;

    myTmp = new char[headerLen + 1];
    strncpy(myTmp, tmpResult, headerLen);
    myTmp[headerLen] = NULL;
    delete (tmpResult);
    *headerOut = myTmp;

    bytesReturnedOut = contenLen;
    closesocket(conn);
    return (result);
}
#endif // HTTPUTIL_H

測試代碼:

#include <string>
#include <stdio.h>
#include "HttpUtil.h"
#include <iostream>
using std::string;
using namespace std;


int main() {
    char *resData = sendRequest("http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp");
    string str = resData;
    cout << endl << str << endl;
    delete resData;
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章