国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C/C++ 發(fā)送與接收HTTP/S請(qǐng)求

這篇具有很好參考價(jià)值的文章主要介紹了C/C++ 發(fā)送與接收HTTP/S請(qǐng)求。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

HTTP(Hypertext Transfer Protocol)是一種用于傳輸超文本的協(xié)議。它是一種無(wú)狀態(tài)的、應(yīng)用層的協(xié)議,用于在計(jì)算機(jī)之間傳輸超文本文檔,通常在 Web 瀏覽器和 Web 服務(wù)器之間進(jìn)行數(shù)據(jù)通信。HTTP 是由互聯(lián)網(wǎng)工程任務(wù)組(IETF)定義的,它是基于客戶端-服務(wù)器模型的協(xié)議,其中客戶端向服務(wù)器發(fā)送請(qǐng)求,服務(wù)器以相應(yīng)的數(shù)據(jù)作為響應(yīng)。HTTP 協(xié)議是建立在 TCP/IP 協(xié)議之上的,通常使用默認(rèn)的端口號(hào)80。

以下是 HTTP 的一些關(guān)鍵特點(diǎn):

  1. 文本協(xié)議: HTTP 是一種文本協(xié)議,通過(guò)純文本的方式傳輸數(shù)據(jù)。這使得它易于閱讀和調(diào)試,但也帶來(lái)了一些安全性方面的問題,因此在需要更安全的通信時(shí),通常會(huì)使用 HTTPS(HTTP Secure)來(lái)加密通信內(nèi)容。
  2. 無(wú)狀態(tài)協(xié)議: HTTP 是一種無(wú)狀態(tài)協(xié)議,意味著每個(gè)請(qǐng)求和響應(yīng)之間都是相互獨(dú)立的,服務(wù)器不會(huì)保存關(guān)于客戶端的任何狀態(tài)信息。這導(dǎo)致了一些問題,例如在進(jìn)行用戶身份驗(yàn)證時(shí),需要額外的機(jī)制來(lái)保持狀態(tài)。
  3. 請(qǐng)求方法: HTTP 定義了一組請(qǐng)求方法,其中最常見的包括 GET(獲取資源)、POST(提交數(shù)據(jù))、PUT(更新資源)、DELETE(刪除資源)等。這些方法指示了客戶端對(duì)服務(wù)器執(zhí)行的操作。
  4. 狀態(tài)碼: 服務(wù)器在響應(yīng)中返回一個(gè)狀態(tài)碼,用于表示請(qǐng)求的處理結(jié)果。常見的狀態(tài)碼包括200(OK,請(qǐng)求成功)、404(Not Found,未找到請(qǐng)求的資源)、500(Internal Server Error,服務(wù)器內(nèi)部錯(cuò)誤)等。
  5. URL(Uniform Resource Locator): HTTP 使用 URL 來(lái)標(biāo)識(shí)和定位網(wǎng)絡(luò)上的資源。URL 包括協(xié)議部分(如 "http://")、主機(jī)名(如 "www.example.com")、路徑部分(如(-lm3g6611ahhripqxl6lpyi/) "/path/to/resource")等。
  6. Header(報(bào)頭): HTTP 的請(qǐng)求和響應(yīng)中都包含頭部信息,用于傳遞關(guān)于消息的附加信息。頭部可以包含各種信息,如身份驗(yàn)證信息、內(nèi)容類型、緩存控制等。

HTTP 是萬(wàn)維網(wǎng)上數(shù)據(jù)通信的基礎(chǔ),它定義了客戶端和服務(wù)器之間的通信規(guī)范。它支持超文本(Hypertext),使得用戶能夠通過(guò)點(diǎn)擊鏈接訪問和瀏覽相關(guān)的文檔和資源,是構(gòu)建 Web 應(yīng)用程序的重要基礎(chǔ)之一。

Web路徑分割

如下提供的代碼片段包含了兩個(gè)用于分割URL的函數(shù):HttpUrlSplitAHttpUrlSplitB。這些函數(shù)的目的是從給定的URL中提取主機(jī)名和路徑。下面是對(duì)兩個(gè)函數(shù)的概述:

  1. HttpUrlSplitA函數(shù):
    • 使用Windows API的InternetCrackUrl函數(shù),該函數(shù)專門用于解析URL。
    • 通過(guò)URL_COMPONENTS結(jié)構(gòu)體來(lái)傳遞和接收URL的不同部分,包括主機(jī)名和路徑。
    • 適用于對(duì)URL進(jìn)行標(biāo)準(zhǔn)化處理的情境,直接調(diào)用系統(tǒng)提供的功能。
  2. HttpUrlSplitB函數(shù):
    • 手動(dòng)實(shí)現(xiàn)對(duì)URL的解析,通過(guò)檢查URL的開頭,然后手動(dòng)提取主機(jī)名和路徑。
    • 對(duì)URL進(jìn)行了一些基本的檢查,如是否以 "http://" 或 "https://" 開頭。
    • 提供了一種更靈活的方式,但需要開發(fā)者自己處理解析邏輯。

總體而言,這兩個(gè)函數(shù)都屬于URL處理的一部分,但選擇使用哪個(gè)函數(shù)可能取決于具體的項(xiàng)目需求和開發(fā)者的偏好。HttpUrlSplitA直接利用Windows API提供的功能,更為直觀。而HttpUrlSplitB則通過(guò)手動(dòng)解析,提供了更多的控制權(quán)。在實(shí)際項(xiàng)目中,選擇取決于開發(fā)者對(duì)項(xiàng)目的要求和對(duì)代碼控制的需求。

InternetCrackUrl 用于解析 URL。它將 URL 拆分為各個(gè)組成部分,例如協(xié)議、主機(jī)名、端口、路徑等。這個(gè)函數(shù)的目的是方便開發(fā)者處理 URL,以便更容易地獲取和使用其中的信息。

以下是關(guān)于 InternetCrackUrl 函數(shù)的一些關(guān)鍵信息:

BOOL InternetCrackUrl(
  _In_  PCTSTR lpszUrl,
  _In_  DWORD   dwUrlLength,
  _In_  DWORD   dwFlags,
  _Out_ LPURL_COMPONENTS lpUrlComponents
);
  • lpszUrl: 指向包含 URL 字符串的空終止字符串的指針。
  • dwUrlLength: URL 字符串的長(zhǎng)度,如果是 NULL 終止字符串,可以設(shè)置為 DWORD(-1)。
  • dwFlags: 一組標(biāo)志,用于指定解析行為。
  • lpUrlComponents: 指向一個(gè) URL_COMPONENTS 結(jié)構(gòu)體的指針,該結(jié)構(gòu)體用于接收 URL 的各個(gè)組成部分。

URL_COMPONENTS 結(jié)構(gòu)體包括以下字段:

typedef struct _URL_COMPONENTS {
  DWORD dwStructSize;
  LPTSTR lpszScheme;
  DWORD dwSchemeLength;
  INTERNET_SCHEME nScheme;
  LPTSTR lpszHostName;
  DWORD dwHostNameLength;
  INTERNET_PORT nPort;
  LPTSTR lpszUserName;
  DWORD dwUserNameLength;
  LPTSTR lpszPassword;
  DWORD dwPasswordLength;
  LPTSTR lpszUrlPath;
  DWORD dwUrlPathLength;
  LPTSTR lpszExtraInfo;
  DWORD dwExtraInfoLength;
} URL_COMPONENTS, *LPURL_COMPONENTS;
  • dwStructSize: 結(jié)構(gòu)體大小。
  • lpszScheme: 指向字符串的指針,該字符串包含 URL 的方案部分(如 "http")。
  • nScheme: 表示 URL 方案的整數(shù)值。
  • lpszHostName: 指向字符串的指針,包含主機(jī)名部分。
  • nPort: 表示端口號(hào)。
  • lpszUserNamelpszPassword: 分別是用戶名和密碼的部分。
  • lpszUrlPath: URL 路徑部分。
  • lpszExtraInfo: 額外信息。

InternetCrackUrl 的返回值為 BOOL 類型,如果函數(shù)成功,返回非零值,否則返回零。函數(shù)成功后,lpUrlComponents 結(jié)構(gòu)體中的字段將被填充。

這個(gè)函數(shù)通常用于在網(wǎng)絡(luò)編程中處理 URL,例如在創(chuàng)建網(wǎng)絡(luò)請(qǐng)求時(shí)提取主機(jī)名、端口和路徑。

#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WinSock2.h>
#include <Windows.h>
#include <string>
#include <WinInet.h>

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

using namespace std;

// 通過(guò)InternetCrackUrl函數(shù)實(shí)現(xiàn)切割
BOOL HttpUrlSplitA(const char* URL, LPSTR pszHostName, LPSTR pszUrlPath)
{
	BOOL bRet = FALSE;
	URL_COMPONENTS url_info = { 0 };
	RtlZeroMemory(&url_info, sizeof(url_info));

	url_info.dwStructSize = sizeof(url_info);

	url_info.dwHostNameLength = MAX_PATH - 1;
	url_info.lpszHostName = pszHostName;

	url_info.dwUrlPathLength = MAX_PATH - 1;
	url_info.lpszUrlPath = pszUrlPath;

	bRet = InternetCrackUrl(URL, 0, 0, &url_info);
	if (FALSE == bRet)
	{
		return FALSE;
	}
	return TRUE;
}

int main(int argc, char* argv[])
{
	char szHostName[1024] = { 0 };
	char szUrlPath[1024] = { 0 };

	BOOL flag = HttpUrlSplitA("http://www.xxx.com/index.html", szHostName, szUrlPath);

	if (flag == TRUE)
	{
		printf("輸出主路徑:%s \n", szHostName);
		printf("輸出子路徑:%s \n", szUrlPath);
	}

	system("pause");
	return 0;
}

運(yùn)行后則會(huì)對(duì)http://www.xxx.com/index.html字符串進(jìn)行路徑切割,并輸出主目錄與子路徑,如下圖所示;

C/C++ 發(fā)送與接收HTTP/S請(qǐng)求

相對(duì)于使用原生API切割,自己實(shí)現(xiàn)也并不難,如下所示,通過(guò)_strnicmp判斷字符串長(zhǎng)度并切割特定的位置,實(shí)現(xiàn)對(duì)字符串的切割;

#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WinSock2.h>
#include <Windows.h>
#include <string>
#include <WinInet.h>

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

using namespace std;

// 自己實(shí)現(xiàn)對(duì)URL路徑的拆分
bool HttpUrlSplitB(const char* pszUrl)
{
	char szHost[256] = { 0 };
	char* ptr = (char*)pszUrl;

	// 判斷開頭是否為http:// 或者 https:// 如果不是則返回-1
	if (_strnicmp(ptr, "http://", 7) == 0)
	{
		ptr = ptr + 7;
	}
	else if (_strnicmp(ptr, "https://", 8) == 0)
	{
		ptr = ptr + 8;
	}
	else
	{
		return false;
	}

	int index = 0;
	while (index < 255 && *ptr && *ptr != '/')
	{
		szHost[index++] = *ptr++;
	}
	szHost[index] = '\0';
	printf("主域名: %s \n 路徑: %s \n", szHost, ptr);
	return true;
}

int main(int argc, char* argv[])
{
	BOOL flag = HttpUrlSplitB("http://www.xxx.com/index.html");

	system("pause");
	return 0;
}

實(shí)現(xiàn)HTTP訪問

HTTP 通常基于TCP(Transmission Control Protocol)。HTTP的本質(zhì)是建立在底層的Socket通信之上的一種應(yīng)用層協(xié)議。

概述HTTP訪問的過(guò)程:

  1. 建立TCP連接: HTTP通信首先需要建立TCP連接,通常默認(rèn)使用TCP的80端口。在建立連接之前,客戶端和服務(wù)器需要通過(guò)DNS解析獲取對(duì)應(yīng)的IP地址。
  2. 發(fā)送HTTP請(qǐng)求: 客戶端通過(guò)Socket向服務(wù)器發(fā)送HTTP請(qǐng)求,請(qǐng)求包括請(qǐng)求方法(GET、POST等)、URL路徑、HTTP協(xié)議版本等信息。同時(shí),客戶端可以附帶一些請(qǐng)求頭(Headers)和請(qǐng)求體(Body),具體內(nèi)容根據(jù)請(qǐng)求的性質(zhì)而定。
  3. 服務(wù)器處理請(qǐng)求: 服務(wù)器接收到客戶端的HTTP請(qǐng)求后,根據(jù)請(qǐng)求的內(nèi)容進(jìn)行處理。處理的方式取決于請(qǐng)求的方法,例如GET請(qǐng)求用于獲取資源,POST請(qǐng)求用于提交數(shù)據(jù)等。服務(wù)器根據(jù)請(qǐng)求返回相應(yīng)的HTTP響應(yīng)。
  4. 發(fā)送HTTP響應(yīng): 服務(wù)器通過(guò)Socket向客戶端發(fā)送HTTP響應(yīng),響應(yīng)包括響應(yīng)狀態(tài)碼、響應(yīng)頭和響應(yīng)體。響應(yīng)狀態(tài)碼表示服務(wù)器對(duì)請(qǐng)求的處理結(jié)果,例如200表示成功,404表示未找到資源,500表示服務(wù)器內(nèi)部錯(cuò)誤等。
  5. 關(guān)閉TCP連接: 一旦HTTP響應(yīng)發(fā)送完畢,服務(wù)器關(guān)閉與客戶端的TCP連接??蛻舳私邮胀觏憫?yīng)后也可以關(guān)閉連接,或者繼續(xù)發(fā)送其他請(qǐng)求。

整個(gè)HTTP訪問的本質(zhì)就是通過(guò)TCP連接在客戶端和服務(wù)器之間傳遞HTTP請(qǐng)求和響應(yīng)。Socket是負(fù)責(zé)實(shí)際數(shù)據(jù)傳輸?shù)牡讓訖C(jī)制,而HTTP協(xié)議則定義了在這個(gè)基礎(chǔ)上進(jìn)行通信的規(guī)范。這種分層的設(shè)計(jì)使得不同的應(yīng)用能夠使用同一個(gè)底層的網(wǎng)絡(luò)傳輸機(jī)制,提高了網(wǎng)絡(luò)通信的靈活性和可擴(kuò)展性。

通常實(shí)現(xiàn)HTTP訪問與主機(jī)訪問相同,唯一的區(qū)別是主機(jī)應(yīng)用的訪問遵循的是服務(wù)端的封包規(guī)則,而對(duì)于Web來(lái)說(shuō)則需要遵循HTTP特有的訪問規(guī)則,在Socket正式接收數(shù)據(jù)之前需要實(shí)現(xiàn)一個(gè)請(qǐng)求規(guī)范,也就是HTTP頭部。

HTTP頭部(HTTP headers)是HTTP請(qǐng)求和響應(yīng)中的重要組成部分,它們包含了與請(qǐng)求或響應(yīng)相關(guān)的信息。HTTP頭部的格式通常是一個(gè)名值對(duì)(key-value pair)的集合,每個(gè)頭部字段由一個(gè)字段名和一個(gè)字段值組成,它們以冒號(hào)分隔,例如:

HeaderName: HeaderValue

HTTP頭部通常以回車符(Carriage Return,\r)和換行符(Line Feed,\n)的組合(\r\n)結(jié)束,每個(gè)頭部字段之間以\r\n分隔。

以下是一些常見的HTTP頭部字段及其示例:

  1. 通用頭部(General Headers):
    • Cache-Control: no-cache
    • Date: Tue, 15 Nov 2022 08:12:31 GMT
    • Connection: keep-alive
  2. 請(qǐng)求頭部(Request Headers):
    • Host: www.example.com
    • User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36
    • Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
  3. 響應(yīng)頭部(Response Headers):
    • Content-Type: text/html; charset=utf-8
    • Content-Length: 12345
    • Server: Apache/2.4.41 (Unix)
  4. 實(shí)體頭部(Entity Headers):
    • Content-Encoding: gzip
    • Last-Modified: Wed, 20 Oct 2022 12:00:00 GMT
    • Etag: "5f0a3e51-20"

HTTP頭部的具體字段和含義可根據(jù)HTTP規(guī)范進(jìn)行擴(kuò)展,不同的應(yīng)用場(chǎng)景和需求可能需要添加自定義的頭部字段。這些頭部字段在HTTP通信中起到了傳遞元信息、控制緩存、指定內(nèi)容類型等作用。在代碼中我們構(gòu)建了一個(gè)如下所示的頭部。

int ret = sprintf(context,
	"GET %s HTTP/1.1 \r\n"
	"Host: %s \r\n"
	"User-Agent: Mozilla/5.0 (Windows NT 10.0) LyShark HttpGet 1.0 \r\n"
	"Accept-Type: */* \r\n"
	"Connection: Close \r\n\r\n",
	szSubPath, szURL);

在這個(gè)HTTP GET請(qǐng)求的基本格式,它包含了一些必要的頭部信息。讓我們逐行解釋:

  1. "GET %s HTTP/1.1 \r\n": 這表示使用HTTP協(xié)議的GET請(qǐng)求方式,%s會(huì)被替換為實(shí)際的URL路徑,HTTP版本為1.1。
  2. "Host: %s \r\n": 這里設(shè)置了HTTP請(qǐng)求的Host頭部,指定了服務(wù)器的主機(jī)名,%s會(huì)被替換為實(shí)際的主機(jī)名。
  3. "User-Agent: Mozilla/5.0 (Windows NT 10.0) LyShark HttpGet 1.0 \r\n": 這是User-Agent頭部,它標(biāo)識(shí)了發(fā)送請(qǐng)求的用戶代理(即瀏覽器或其他客戶端)。這里的字符串表示使用Mozilla瀏覽器5.0版本,運(yùn)行在Windows NT 10.0操作系統(tǒng)上,LyShark HttpGet 1.0表示這個(gè)請(qǐng)求的自定義用戶代理。
  4. "Accept-Type: */* \r\n": 這是Accept-Type頭部,表示客戶端可以接受任意類型的響應(yīng)內(nèi)容。
  5. "Connection: Close \r\n\r\n": Connection頭部表示在完成請(qǐng)求后關(guān)閉連接,避免保持連接。\r\n\r\n表示頭部結(jié)束,之后是可選的請(qǐng)求體。

綜合起來(lái),這個(gè)HTTP GET請(qǐng)求的目的是獲取指定URL路徑的資源,請(qǐng)求頭部包含了一些必要的信息,例如主機(jī)名、用戶代理等。這是一個(gè)基本的HTTP請(qǐng)求格式,可以根據(jù)具體需求添加或修改頭部信息。

#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WinSock2.h>
#include <Windows.h>
#include <string>
#include <WinInet.h>

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

using namespace std;

// 通過(guò)InternetCrackUrl函數(shù)實(shí)現(xiàn)切割
BOOL HttpUrlSplitA(const char* URL, LPSTR pszHostName, LPSTR pszUrlPath)
{
	BOOL bRet = FALSE;
	URL_COMPONENTS url_info = { 0 };
	RtlZeroMemory(&url_info, sizeof(url_info));

	url_info.dwStructSize = sizeof(url_info);

	url_info.dwHostNameLength = MAX_PATH - 1;
	url_info.lpszHostName = pszHostName;

	url_info.dwUrlPathLength = MAX_PATH - 1;
	url_info.lpszUrlPath = pszUrlPath;

	bRet = InternetCrackUrl(URL, 0, 0, &url_info);
	if (FALSE == bRet)
	{
		return FALSE;
	}
	return TRUE;
}

// Get方式訪問頁(yè)面
char* Curl(const char* szURL, const char* szSubPath, const int port)
{
	WSADATA wsaData;
	WSAStartup(0x0202, &wsaData);

	char* context = new char[1024 * 8];
	int ret = sprintf(context,
		"GET %s HTTP/1.1 \r\n"
		"Host: %s \r\n"
		"User-Agent: Mozilla/5.0 (Windows NT 10.0) LyShark HttpGet 1.0 \r\n"
		"Accept-Type: */* \r\n"
		"Connection: Close \r\n\r\n",
		szSubPath, szURL);

	SOCKADDR_IN addr;
	SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
	addr.sin_addr.S_un.S_addr = 0;
	addr.sin_port = htons(0);
	addr.sin_family = AF_INET;

	ret = bind(sock, (const sockaddr*)&addr, sizeof(SOCKADDR_IN));
	hostent* local_addr = gethostbyname(szURL);

	if (local_addr)
	{
		ULONG ip = *(ULONG*)local_addr->h_addr_list[0];
		addr.sin_addr.S_un.S_addr = ip;
		addr.sin_port = htons(port);

		ret = connect(sock, (const sockaddr*)&addr, sizeof(SOCKADDR_IN));
		if (ret == NOERROR)
		{
			ret = send(sock, (const char*)context, (int)strlen(context), 0);
			do
			{
				ret = recv(sock, context, 8191, 0);
				if (ret <= 0)
				{
					break;
				}
				context[ret] = '\0';
				printf("\n%s\n\n", context);
			} while (TRUE);
		}
	}
	closesocket(sock);
	WSACleanup();
	return context;
}

// 訪問指定頁(yè)面
char* HttpGet(const char* szURL, const int port)
{
	char master_url[1024] = { 0 };
	char slave_url[1024] = { 0 };
	char* curl_context = nullptr;

	// 將完整路徑切割為主路徑與次路徑
	BOOL ref = HttpUrlSplitA(szURL, master_url, slave_url);
	if (TRUE == ref)
	{
		// 獲取所有網(wǎng)頁(yè)內(nèi)容
		curl_context = Curl(master_url, slave_url, port);
		return curl_context;
	}
	return 0;
}

int main(int argc, char* argv[])
{
	char *szBuffer = HttpGet("http://www.lyshark.com/index.html", 80);

	// printf("%s \n", szBuffer);
	
	system("pause");
	return 0;
}

運(yùn)行上述代碼則會(huì)自動(dòng)請(qǐng)求http://www.lyshark.com/index.html路徑的80端口,以獲取返回參數(shù)信息,如下圖所示;

C/C++ 發(fā)送與接收HTTP/S請(qǐng)求

實(shí)現(xiàn)HTTPS訪問

HTTPS的訪問與HTTP基本類似,同樣是通過(guò)Socket訪問端口,同樣是發(fā)送特定的GET請(qǐng)求頭,唯一的不同在于當(dāng)鏈接被建立后,對(duì)于HTTPS來(lái)說(shuō)多出一個(gè)TLS協(xié)商的過(guò)程,這是為了保護(hù)傳輸時(shí)的安全而增加的安全特定,為了能實(shí)現(xiàn)訪問我們需要使用OpenSSL庫(kù)對(duì)完成TLS的握手才行。

OpenSSL 是一個(gè)強(qiáng)大的開源軟件庫(kù),提供了一系列的密碼學(xué)工具和庫(kù)函數(shù),廣泛用于網(wǎng)絡(luò)安全應(yīng)用的開發(fā)。它支持許多密碼學(xué)協(xié)議和算法,包括 SSL(Secure Sockets Layer)和 TLS(Transport Layer Security)協(xié)議,用于在計(jì)算機(jī)網(wǎng)絡(luò)上實(shí)現(xiàn)安全通信。

HTTPS握手過(guò)程是建立在TLS(Transport Layer Security)協(xié)議之上的。TLS是SSL(Secure Sockets Layer)的繼任者,用于在計(jì)算機(jī)網(wǎng)絡(luò)上保障通信安全。以下是HTTPS握手的基本流程:

  1. 客戶端Hello:
    • 客戶端向服務(wù)器發(fā)送ClientHello消息,其中包含支持的TLS版本、支持的加密算法、支持的壓縮算法等信息。
  2. 服務(wù)器Hello:
    • 服務(wù)器從客戶端提供的信息中選擇一個(gè)合適的TLS版本和加密套件,并向客戶端發(fā)送ServerHello消息,同時(shí)發(fā)送服務(wù)器證書。
  3. 認(rèn)證:
    • 客戶端驗(yàn)證服務(wù)器發(fā)送的證書是否有效,通常包括證書的頒發(fā)機(jī)構(gòu)(CA)的簽名驗(yàn)證??蛻舳诉€可以驗(yàn)證證書中包含的域名是否匹配正在連接的域名。
  4. 密鑰交換:
    • 客戶端生成一個(gè)隨機(jī)值,使用服務(wù)器的公鑰加密該隨機(jī)值,然后將加密后的數(shù)據(jù)發(fā)送給服務(wù)器。服務(wù)器使用自己的私鑰解密,得到客戶端生成的隨機(jī)值。這兩個(gè)隨機(jī)值將用于生成對(duì)話密鑰。
  5. 對(duì)話密鑰的生成:
    • 客戶端和服務(wù)器使用客戶端生成的隨機(jī)值、服務(wù)器生成的隨機(jī)值以及前面協(xié)商的算法,通過(guò)一系列協(xié)商步驟生成對(duì)話密鑰。
  6. 加密通信:
    • 客戶端和服務(wù)器使用生成的對(duì)話密鑰對(duì)通信進(jìn)行加密和解密,確保數(shù)據(jù)的隱私和完整性。

整個(gè)握手過(guò)程確保了通信雙方的身份驗(yàn)證、密鑰的安全協(xié)商以及通信內(nèi)容的保密性和完整性。握手完成后,客戶端和服務(wù)器使用協(xié)商得到的對(duì)話密鑰進(jìn)行加密通信,從而實(shí)現(xiàn)了安全的HTTPS連接。

如下所示代碼以演示訪問必應(yīng)為例,需要獲取必應(yīng)的IP地址,以及在GET請(qǐng)求中更改訪問域名為BING;

#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <iostream>
#include <WinSock2.h>
#include <openssl/ssl.h>

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

using namespace std;

const wchar_t* GetWC(const char* c)
{
	const size_t cSize = strlen(c) + 1;
	wchar_t* wc = new wchar_t[cSize];
	mbstowcs(wc, c, cSize);
	return wc;
}

int main(int argc, char* argv[])
{
	WSADATA WSAData;
	SOCKET sock;
	struct sockaddr_in ClientAddr;

	if (WSAStartup(MAKEWORD(2, 0), &WSAData) != SOCKET_ERROR)
	{
		ClientAddr.sin_family = AF_INET;
		ClientAddr.sin_port = htons(443);
		ClientAddr.sin_addr.s_addr = inet_addr("202.89.233.101");

		sock = socket(AF_INET, SOCK_STREAM, 0);
		int Ret = connect(sock, (LPSOCKADDR)&ClientAddr, sizeof(ClientAddr));
		if (Ret == 0)
		{
		}
	}

	// 初始化OpenSSL庫(kù) 創(chuàng)建SSL會(huì)話環(huán)境等
	SSL_CTX* pctxSSL = SSL_CTX_new(TLSv1_2_client_method());
	if (pctxSSL == NULL)
	{
		return -1;
	}
	SSL* psslSSL = SSL_new(pctxSSL);
	if (psslSSL == NULL)
	{
		return -1;
	}
	SSL_set_fd(psslSSL, sock);
	INT iErrorConnect = SSL_connect(psslSSL);
	if (iErrorConnect < 0)
	{
		return -1;
	}
	std::wcout << "SLL ID: " << SSL_get_cipher(psslSSL) << std::endl;

	// 發(fā)包
	std::string strWrite =
		"GET https://cn.bing.com/ HTTP/1.1\r\n"
		"Host: cn.bing.com\r\n"
		"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0 \r\n"
		"Accept-Type: */* \r\n"
		"Connection: close\r\n\r\n";

	INT iErrorWrite = SSL_write(psslSSL, strWrite.c_str(), strWrite.length()) < 0;
	if (iErrorWrite < 0)
	{
		return -1;
	}

	// 收包并輸出
	LPSTR lpszRead = new CHAR[8192];
	INT iLength = 1;
	while (iLength >= 1)
	{
		iLength = SSL_read(psslSSL, lpszRead, 8192 - 1);
		if (iLength < 0)
		{
			std::wcout << "Error SSL_read" << std::endl;
			delete[] lpszRead;
			return -1;
		}
		lpszRead[iLength] = TEXT('\0');
		std::wcout << GetWC(lpszRead);
	}
	delete[] lpszRead;

	closesocket(sock);
	WSACleanup();

	system("pause");
	return 0;
}

成勛運(yùn)行后將會(huì)對(duì)必應(yīng)發(fā)起https訪問,并獲取返回值信息,如下圖所示;

C/C++ 發(fā)送與接收HTTP/S請(qǐng)求文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-747365.html

到了這里,關(guān)于C/C++ 發(fā)送與接收HTTP/S請(qǐng)求的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 命令模式——請(qǐng)求發(fā)送者與接收者解耦

    命令模式——請(qǐng)求發(fā)送者與接收者解耦

    在軟件開發(fā)中,經(jīng)常需要向某些對(duì)象發(fā)送請(qǐng)求(調(diào)用其中的某個(gè)或某些方法),但是并不知道請(qǐng)求的接收者是誰(shuí),也不知道被請(qǐng)求的操作是哪個(gè)。此時(shí),特別希望能夠以一種松耦合的方式來(lái)設(shè)計(jì)軟件,使得請(qǐng)求發(fā)送者與請(qǐng)求接收者能夠消除彼此之間的耦合,讓對(duì)象之間的調(diào)用

    2024年02月14日
    瀏覽(20)
  • 命令模式-請(qǐng)求發(fā)送者與接收者解耦

    命令模式-請(qǐng)求發(fā)送者與接收者解耦

    ?去小餐館吃飯的時(shí)候,顧客直接跟廚師說(shuō)想要吃什么菜,然后廚師再開始炒菜。去大點(diǎn)的餐館吃飯時(shí),我們是跟服務(wù)員說(shuō)想吃什么菜,然后服務(wù)員把這信息傳到廚房,廚師根據(jù)這些訂單信息炒菜。為什么大餐館不省去這個(gè)步驟,像小餐管那樣點(diǎn)菜呢?原因主要有以下幾點(diǎn):

    2024年02月14日
    瀏覽(22)
  • http發(fā)送和接收?qǐng)D片json文件

    1、先將圖片轉(zhuǎn)換為base64格式 2、將數(shù)據(jù)以json格式進(jìn)行發(fā)送 其中?ImgInfo 類為: 上述代碼中json數(shù)據(jù)有五個(gè)部分:image為圖片數(shù)據(jù),level是告警等級(jí),rtsp為數(shù)據(jù)流地址,type是算法類型,label是算法標(biāo)簽等,所以數(shù)據(jù)發(fā)送為這五個(gè)內(nèi)容。 HttpServer.cpp如下:? ?HttpServer.h如下: httpu

    2024年02月07日
    瀏覽(158)
  • processing:使用processing.net向flask發(fā)送請(qǐng)求并接收響應(yīng)

    Network Library使在互聯(lián)網(wǎng)上跨機(jī)器讀寫數(shù)據(jù)成為可能,它允許在processing中創(chuàng)建客戶端和服務(wù)器,客戶端能夠讀取數(shù)據(jù)并將數(shù)據(jù)寫入服務(wù)器 客戶端連接到服務(wù)器并來(lái)回發(fā)送數(shù)據(jù),如果連接出現(xiàn)問題,則會(huì)引發(fā)異常 Constructors:Client(parent, host, port) Parameters: -parent:通常使用\\\"this\\\"

    2024年02月16日
    瀏覽(23)
  • 用python通過(guò)http實(shí)現(xiàn)文件傳輸,分為發(fā)送端和接收端

    要使用Python通過(guò)HTTP實(shí)現(xiàn)文件傳輸,可以使用Python的 requests 庫(kù)來(lái)發(fā)送和接收HTTP請(qǐng)求。以下是一個(gè)示例代碼,其中包括發(fā)送端和接收端的實(shí)現(xiàn)。 發(fā)送端: 接收端: 在這個(gè)示例中,發(fā)送端使用 requests.post() 方法發(fā)送文件到指定的URL。接收端使用Flask框架創(chuàng)建一個(gè)HTTP服務(wù)器,并在

    2024年02月15日
    瀏覽(29)
  • Http中post/get請(qǐng)求參數(shù)接收

    Http中post/get請(qǐng)求參數(shù)接收

    Http請(qǐng)求報(bào)文示例圖如下: ? ①是請(qǐng)求方法,GET和POST是最常見的HTTP方法,除此以外還包括DELETE、HEAD、OPTIONS、PUT、TRACE。不過(guò),當(dāng)前的大多數(shù)瀏覽器只支持GET和POST,Spring 3.0提供了一個(gè)HiddenHttpMethodFilter,允許通過(guò)_method的表單參數(shù)指定這些特殊的HTTP方法(實(shí)際上還是通過(guò)POST提

    2024年01月25日
    瀏覽(35)
  • Nginx接收Http協(xié)議請(qǐng)求轉(zhuǎn)發(fā)使用Https協(xié)議

    公司使用阿里的apigateway,規(guī)定不太友好,同是SIT環(huán)境,A系統(tǒng)的SIT1環(huán)境居然不能調(diào)用B系統(tǒng)的SIT2環(huán)境的接口。因?yàn)楦鱾€(gè)系統(tǒng)之間部署的SIT環(huán)境數(shù)量不同A系統(tǒng)可能只有1套,B系統(tǒng)可能有8套,這樣的話,可能會(huì)隨時(shí)切換調(diào)用B系統(tǒng)的環(huán)境,管理員不允許,于是想著用Nginx做下轉(zhuǎn)發(fā)。

    2024年02月08日
    瀏覽(28)
  • bat 發(fā)送http請(qǐng)求

    其中,-X POST 表示發(fā)送 POST 請(qǐng)求;-H 指定請(qǐng)求頭信息;-d 指定 POST 請(qǐng)求的數(shù)據(jù)體。 setlocal 和 endlocal 是一對(duì)批處理命令,用于控制局部環(huán)境變量的范圍。 setlocal 命令將創(chuàng)建一個(gè)新的環(huán)境變量,該環(huán)境變量是當(dāng)前環(huán)境變量的一個(gè)副本。這樣做的目的是為了在批處理文件中創(chuàng)建一

    2024年02月11日
    瀏覽(17)
  • java發(fā)送Http請(qǐng)求

    使用java 11添加的HttpClient新API發(fā)送Http(Https)請(qǐng)求 HTTP客戶端是在Java 11中添加的。它可以用于通過(guò)網(wǎng)絡(luò)請(qǐng)求HTTP資源。它支持 HTTP / 1.1和HTTP / 2(同步和異步編程模型),將請(qǐng)求和響應(yīng)主體作為反應(yīng)流處理,并遵循熟悉的構(gòu)建器模式。 參考文章:https://blog.csdn.net/allway2/article/detail

    2023年04月12日
    瀏覽(20)
  • HTTP四大參數(shù)類型及請(qǐng)求參數(shù)的方式和如何接收

    HTTP四大參數(shù)類型及請(qǐng)求參數(shù)的方式和如何接收

    請(qǐng)求頭參數(shù)顧名思義,是存放在請(qǐng)求頭中發(fā)送給服務(wù)器的參數(shù),服務(wù)器通過(guò)解析請(qǐng)求頭獲取參數(shù)內(nèi)容。通常會(huì)存放本次請(qǐng)求的基本設(shè)置,以幫助服務(wù)器理解并解析本次請(qǐng)求的body體。 參數(shù)形式如: 在我們的SpringBoot中,通過(guò) @RequestHeader 注解可以獲取到。 Spring Boot 讀取http head

    2024年02月03日
    瀏覽(17)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包