OpenSSL的下載和環(huán)境配置
請參考:openssl下載安裝教程
步驟:官網(wǎng)下載->安裝到選定目錄->配置環(huán)境變量->打開命令窗口檢查是否安裝成功
注意:
打開命令窗口(快捷鍵win+r,在彈出窗口內(nèi)輸入cmd按回車),輸入命令openssl version如果顯示openssl版本則表示安裝成功。
我出現(xiàn)的問題:明明安裝上了卻顯示
B:>openssl version
‘openssl’ 不是內(nèi)部或外部命令,也不是可運(yùn)行的程序
或批處理文件。
解決方法:更改到lib目錄,輸入命令:
B:\OpenSSL-Win64\lib>openssl.exe
因?yàn)槲业陌姹緊penssl.exe文件在lib目錄下,可以在OpenSSL-Win64文件夾里直接搜索openssl.exe,就知道在哪個(gè)目錄下了。
運(yùn)行之后再輸入openssl version就會顯示版本,例:
B:\OpenSSL-Win64\bin>openssl version
OpenSSL 3.1.0 14 Mar 2023 (Library: OpenSSL 3.1.0 14 Mar 2023)
出現(xiàn)版本信息代表安裝成功。
visual studio項(xiàng)目環(huán)境配置
我使用visual studio2019版本,以下步驟僅供參考。
1.在屬性頁頂端右邊,把平臺改成x64(根據(jù)自己需要),點(diǎn)擊右側(cè)配置管理器按鈕,將此項(xiàng)目的平臺改成x64(根據(jù)自己需要)。
2.打開項(xiàng)目界面,在上方菜單欄選擇項(xiàng)目->屬性
3.在左側(cè)選擇VC++目錄,選擇包含目錄,編輯,粘貼openssl的include目錄的絕對路徑。
例如:B:\OpenSSL-Win64\include
選擇庫目錄,編輯,粘貼openssl的lib目錄的絕對路徑
例如:B:\OpenSSL-Win64\lib
4.選擇左側(cè)C/C++常規(guī),選擇附加包含目錄,編輯,粘貼openssl的include目錄的絕對路徑。
例如:B:\OpenSSL-Win64\include
5.選擇左側(cè)鏈接器,選擇下側(cè)輸入,選擇右側(cè)附加依賴項(xiàng),編輯,寫入libssl.lib,libcrypto.lib的路徑。在lib目錄中,打開自己下載的openssl文件夾看一下具體是哪個(gè)路徑,不同版本可能不同,我使用的版本是 3.1.0 14
例如:
B:\OpenSSL-Win64\lib\libssl.lib
B:\OpenSSL-Win64\lib\libcrypto.lib
注意:編譯器所有無法識別SSL…的問題都是環(huán)境沒配置好,再仔細(xì)看一下上述步驟,都是一步步配置過的,親測OK。
代碼實(shí)現(xiàn)
思路
文章來源:http://www.zghlxwxcb.cn/news/detail-853090.html
源碼
#include<stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <openssl/ssl.h>
#pragma comment(lib, "Ws2_32.lib")
int main() {
// 初始化 Winsock(windows套接字)
/*WSADATA是windows API定義的一個(gè)結(jié)構(gòu),存儲關(guān)于winsock實(shí)現(xiàn)的詳細(xì)信息*/
WSADATA wsaData;
/*WSAStartup()這個(gè)函數(shù)用于初始化Winsock庫,
MAKEWORD(2, 2)相當(dāng)于創(chuàng)建了一個(gè)對Winsock 2.2的版本請求,
&wsaData用于將wsaData地址結(jié)構(gòu)傳入函數(shù)
*/
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
/*
WSAStartup返回了一個(gè)非0的值則代表初始化失敗
*/
printf("WSAStartup failed\n");
return 1;
}
printf("客戶端Winsock初始化成功\n");
printf("————————————————————\n");
//創(chuàng)建客戶端對象
/*聲明一個(gè)整型變量socket_fd用來存儲套接字描述符
*/
int socket_fd;
/*socket()函數(shù)用于創(chuàng)建一個(gè)新的套接字,
AF_INET指定了地址族為ipv4,
SOCK_STREAM指定了套接字類型為流式套接字,即TCP
第三個(gè)參數(shù),通常用來指定協(xié)議
*/
if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0))== 0){
perror("socket failed");
exit(EXIT_FAILURE);
}
/*聲明一個(gè)結(jié)構(gòu)體變量sock_addr,用于存儲套接字地址信息(IPv4)
*/
struct sockaddr_in sock_addr;
sock_addr.sin_family = AF_INET; //使用ipv4地址族
/*htons() 函數(shù)用于將主機(jī)字節(jié)順序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序,確保在不同架構(gòu)的計(jì)算機(jī)上,端口號的表示都是一致的。
*/
sock_addr.sin_port = htons(8080); //設(shè)置端口號為8080
//設(shè)置網(wǎng)絡(luò)ip
/*調(diào)用inet_pton()函數(shù)將字符串形式的IP地址轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序的二進(jìn)制IP地址,
并存儲到sock_addr.sin_addr中
*/
if (inet_pton(AF_INET, "192.168.1.128", &sock_addr.sin_addr) <= 0) {
/*inet_pton()函數(shù)返回值如果小于等于零,表示轉(zhuǎn)換失敗*/
perror("inet_pton() failed");
exit(EXIT_FAILURE);
}
printf("創(chuàng)建客戶端對象成功,嘗試連接服務(wù)器\n");
printf("————————————————————\n");
//連接服務(wù)器
if ((connect(socket_fd, (struct sockaddr*)&sock_addr, sizeof(sock_addr)) < 0)) {
perror("connect failed\n");
exit(EXIT_FAILURE);
}
printf("對服務(wù)器發(fā)起連接\n");
//初始化openssl庫
//SSL庫初始化
SSL_library_init();
//載入所有SSL算法
SSLeay_add_ssl_algorithms();
//載入所有SSL錯(cuò)誤消息
SSL_load_error_strings();
//創(chuàng)建SSL會話環(huán)境
//使用 TLS_client_method() 函數(shù)創(chuàng)建了一個(gè) SSL 上下文結(jié)構(gòu)(SSL_CTX)
/*TLS_client_method()
const SSL_METHOD *TLS_client_method(void);
函數(shù)的返回值用于指定SSL/TSL連接使用的方法,這個(gè)方法指定了客戶端如何與服務(wù)器端建立連接。
通過調(diào)用該函數(shù),獲取一個(gè)用于SSL/TSL客戶端的SSL_METHOD結(jié)構(gòu),這個(gè)結(jié)構(gòu)被傳遞給SSL_CTX_new()函數(shù),用于創(chuàng)建SSL_CTX上下文對象。
SSL_CTX_new()
SSL_CTX *SSL_CTX_new(const SSL_METHOD *method);
根據(jù)指定的SSL/TLS方法創(chuàng)建一個(gè)SSL/TSL上下文對象,該上下文對象包含了SSL/TSL連接的所有配置信息,包括加密算法、證書、私鑰等。
若創(chuàng)建失敗返回NULL。
*/
SSL_CTX* pctxSSL = SSL_CTX_new(TLS_client_method());
if (pctxSSL == NULL) {
printf("error ssl_ctx_new\n");
return -1;
}
/*
基于之前創(chuàng)建的 SSL 上下文(SSL_CTX),創(chuàng)建了一個(gè) SSL 對象,該對象將使用指定的上下文對象來配置 SSL/TLS 連接
*/
SSL* psslSSL = SSL_new(pctxSSL);
if (psslSSL == NULL) {
printf("error ssl_new\n");
}
/*SSL_set_fd()函數(shù)用于將一個(gè)套接字文件描述符與SSL對象關(guān)聯(lián)起來,從而使SSL對象可以在該套接字上進(jìn)行SSL/TSL加密通信。
*/
SSL_set_fd(psslSSL, socket_fd);
//使用之前創(chuàng)建的 SSL 結(jié)構(gòu)(SSL),建立了 SSL 連接。
/*SSL_connect()函數(shù)嘗試與遠(yuǎn)程服務(wù)器建立安全連接。iErrorConnect表示連接的狀態(tài),如果連接失敗返回值小于零。
*/
INT iErrorConnect = SSL_connect(psslSSL);
if (iErrorConnect < 0) {
//打印錯(cuò)誤碼
printf("error SSL_connect,iErrorConnect=%d\n", iErrorConnect);
//打印當(dāng)前SSL連接所使用的加密算法
/*SSL_get_cipher() 函數(shù)返回一個(gè)指向當(dāng)前 SSL 連接所使用的加密算法字符串的指針。
*/
}
/*SSL_get_cipher() 函數(shù)返回一個(gè)指向當(dāng)前 SSL 連接所使用的加密算法字符串的指針。
*/
printf("SSL connection using:%s\n", SSL_get_cipher(psslSSL));
//準(zhǔn)備http請求
char http[] = "GET /index.html HTTP/1.1\r\nHost: 192.168.10.124:8080\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nMozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36\r\ntext/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9\r\n\r\n";
//通過SSL連接發(fā)送http get請求,發(fā)送成功則返回發(fā)送的字節(jié)數(shù),否則返回一個(gè)負(fù)值表示發(fā)送失敗
/*SSL_write()函數(shù)用于在SSL連接上寫入數(shù)據(jù),將http中的數(shù)據(jù)寫入到與psslSSL相關(guān)的SSL連接中
* 返回值小于零表示寫入失敗
*/
INT iErroeWrite = SSL_write(psslSSL,http,strlen(http));
if (iErroeWrite<0) {
printf("error SSL_write\n");
return -1;
}
char buf[2048] = {0};
/*
*/
INT iLength = 1;
/*調(diào)用SSL_read函數(shù)從SSL連接中讀取數(shù)據(jù)
第一個(gè)參數(shù):SSL連接對象
第二個(gè)參數(shù):指向接收緩沖區(qū)的指針
第三個(gè)參數(shù):緩沖區(qū)的大小
函數(shù)返回讀取到的字節(jié)數(shù)
*/
while ((iLength=SSL_read(psslSSL,buf, sizeof(buf)))>=1) {
}
printf("讀取數(shù)據(jù)成功\n");
printf("服務(wù)器端給出的回應(yīng)是%s\n", buf);
//關(guān)閉SSL連接
SSL_shutdown(psslSSL);
//釋放SSL數(shù)據(jù)結(jié)構(gòu)
SSL_free(psslSSL);
//釋放SSL_CTX數(shù)據(jù)結(jié)構(gòu)
SSL_CTX_free(pctxSSL);
//關(guān)閉套接字
closesocket(socket_fd);
WSACleanup();
return 0;
}
參考鏈接
1.c語言https實(shí)現(xiàn)客戶端
2.visual studio openssl環(huán)境配置
3.https協(xié)議詳解文章來源地址http://www.zghlxwxcb.cn/news/detail-853090.html
到了這里,關(guān)于c語言實(shí)現(xiàn)https客戶端 源碼+詳細(xì)注釋(OpenSSL下載,visual studio編譯器環(huán)境配置)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!