C++ 獲取URL內容的例項
阿新 • • 發佈:2020-12-10
我就廢話不多說了,大家還是直接看程式碼吧~
以下內容摘自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 &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,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,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,"\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,bufSize); thisReadSize = recv (conn,readBuffer,bufSize,0); if ( thisReadSize <= 0 ) break; tmpResult = (char *)realloc(tmpResult,thisReadSize + totalBytesRead); memcpy(tmpResult + totalBytesRead,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; }
補充知識:C++處理URL的方法,專案有用到,過程記錄如下
由於這塊需要轉換成unicode碼,也就是將字串傳換成unicode碼,因此需要對輸入的字串做處理,同時又分兩種情況,中文 非中文的處理,要區別對待,首先要對輸入的字串進行識別:
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; }
然後要進行相應轉換
//--------------------------------------------------------------------- //函式:W2C //功能:將16位wchar_t轉換為 8位char[2] //引數:w_cn為待轉換的16位字元,c_cn[]為轉換後的8位字元 //備註:wchar_t的高位位元組應該儲存在char陣列的低位位元組 //作者:xxxx //--------------------------------------------------------------------- void W2C(wchar_t w_cn,char c_cn[]){c_cn[0] = w_cn >> 8 ;c_cn[1] = (char)w_cn ;}
然後主體轉換程式碼:
//------------------------------------------------------------------- //函式:ToHex //功能:將16位字串轉換為十六進位制字串 //引數:待轉換的字串,字串長度 //返回值:轉換後的字串 //作者: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,(LPCWSTR)str,-1,buff,MAX_PATH,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; }
到這裡基本上結束了~也查看了一些資料,雖說這個功能簡單,但是過程有點曲折。但總算完成了,留個紀念吧~希望對其他人有幫助~希望大家多多支援我們。