C++ 獲取URL內(nèi)容的實例
更新時間:2020年12月10日 10:09:08 作者:iYAO
這篇文章主要介紹了C++ 獲取URL內(nèi)容的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
我就廢話不多說了,大家還是直接看代碼吧~
以下內(nèi)容摘自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;
}
補(bǔ)充知識:C++處理URL的方法,項目有用到,過程記錄如下
由于這塊需要轉(zhuǎn)換成unicode碼,也就是將字符串傳換成unicode碼,因此需要對輸入的字符串做處理,同時又分兩種情況,中文 非中文的處理,要區(qū)別對待,首先要對輸入的字符串進(jìn)行識別:
int 是不是中文(char *str)
{
char ch;
while (1)
{
ch = *str++;
if (ch == 0)
{
break;
}
if (ch&0x80)
{
if (*str & 0x80)
{
return true;
}
}
else
{
return false;
}
}
return 0;
}
然后要進(jìn)行相應(yīng)轉(zhuǎn)換
//---------------------------------------------------------------------
//函數(shù):W2C
//功能:將16位wchar_t轉(zhuǎn)換為 8位char[2]
//參數(shù):w_cn為待轉(zhuǎn)換的16位字符,c_cn[]為轉(zhuǎn)換后的8位字符
//備注:wchar_t的高位字節(jié)應(yīng)該存儲在char數(shù)組的低位字節(jié)
//作者:xxxx
//---------------------------------------------------------------------
void W2C(wchar_t w_cn , char c_cn[]){c_cn[0] = w_cn >> 8 ;c_cn[1] = (char)w_cn ;}
然后主體轉(zhuǎn)換代碼:
//-------------------------------------------------------------------
//函數(shù):ToHex
//功能:將16位字符串轉(zhuǎn)換為十六進(jìn)制字符串
//參數(shù):待轉(zhuǎn)換的字符串,字符串長度
//返回值:轉(zhuǎn)換后的字符串
//作者:xxxx
//-------------------------------------------------------------------
CString ToHex(CString Data, long nDataLength)
{
CString sResult;
for (long nLoop=0; nLoop<nDataLength; nLoop++)
{
wchar_t ch = Data.GetAt(nLoop);
CHAR buff[MAX_PATH] = {0};
LPCWSTR str = &ch;
WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)str, -1, buff, MAX_PATH, 0, 0);
if (IncludeChinese(buff))
{
char c_cn[2]={'0'};
W2C(ch,c_cn);
static const char *hex = "0123456789ABCDEF";
for(int i=0;i<2;i++)
{
unsigned char chHexA = hex[((unsigned char)(c_cn[i]) >> 4) & 0x0f];
unsigned char chHexB = hex[(unsigned char)(c_cn[i]) & 0x0f];
sResult += (char)chHexA;
sResult += (char)chHexB;
}
}
else
{
sResult += ch;
}
}
return sResult;
}
到這里基本上結(jié)束了~也查看了一些資料,雖說這個功能簡單,但是過程有點曲折。但總算完成了,留個紀(jì)念吧~希望對其他人有幫助~希望大家多多支持腳本之家。
相關(guān)文章
C++中volatile和mutable關(guān)鍵字用法詳解
這篇文章主要介紹了C++中volatile和mutable關(guān)鍵字用法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02

