C/C++ 发送与接收HTTP/S请求
HTTP(Hypertext Transfer Protocol)是一种用于传输超文本的协议。它是一种无状态的、应用层的协议,用于在计算机之间传输超文本文档,通常在 Web 浏览器和 Web 服务器之间进行数据通信。HTTP 是由互联网工程任务组(IETF)定义的,它是基于客户端-服务器模型的协议,其中客户端向服务器发送请求,服务器以相应的数据作为响应。HTTP 协议是建立在 TCP/IP 协议之上的,通常使用默认的端口号80。
以下是 HTTP 的一些关键特点:
- 文本协议: HTTP 是一种文本协议,通过纯文本的方式传输数据。这使得它易于阅读和调试,但也带来了一些安全性方面的问题,因此在需要更安全的通信时,通常会使用 HTTPS(HTTP Secure)来加密通信内容。
- 无状态协议: HTTP 是一种无状态协议,意味着每个请求和响应之间都是相互独立的,服务器不会保存关于客户端的任何状态信息。这导致了一些问题,例如在进行用户身份验证时,需要额外的机制来保持状态。
- 请求方法: HTTP 定义了一组请求方法,其中最常见的包括 GET(获取资源)、POST(提交数据)、PUT(更新资源)、DELETE(删除资源)等。这些方法指示了客户端对服务器执行的操作。
- 状态码: 服务器在响应中返回一个状态码,用于表示请求的处理结果。常见的状态码包括200(OK,请求成功)、404(Not Found,未找到请求的资源)、500(Internal Server Error,服务器内部错误)等。
- URL(Uniform Resource Locator): HTTP 使用 URL 来标识和定位网络上的资源。URL 包括协议部分(如 “http://”)、主机名(如 “www.xxx.com”)、路径部分等。
- Header(报头): HTTP 的请求和响应中都包含头部信息,用于传递关于消息的附加信息。头部可以包含各种信息,如身份验证信息、内容类型、缓存控制等。
HTTP 是万维网上数据通信的基础,它定义了客户端和服务器之间的通信规范。它支持超文本(Hypertext),使得用户能够通过点击链接访问和浏览相关的文档和资源,是构建 Web 应用程序的重要基础之一。
Web路径分割
如下提供的代码片段包含了两个用于分割URL的函数:HttpUrlSplitA
和HttpUrlSplitB
。这些函数的目的是从给定的URL中提取主机名和路径。下面是对两个函数的概述:
HttpUrlSplitA
函数:- 使用Windows API的
InternetCrackUrl
函数,该函数专门用于解析URL。 - 通过
URL_COMPONENTS
结构体来传递和接收URL的不同部分,包括主机名和路径。 - 适用于对URL进行标准化处理的情境,直接调用系统提供的功能。
- 使用Windows API的
HttpUrlSplitB
函数:- 手动实现对URL的解析,通过检查URL的开头,然后手动提取主机名和路径。
- 对URL进行了一些基本的检查,如是否以 “http://” 或 “https://” 开头。
- 提供了一种更灵活的方式,但需要开发者自己处理解析逻辑。
总体而言,这两个函数都属于URL处理的一部分,但选择使用哪个函数可能取决于具体的项目需求和开发者的偏好。HttpUrlSplitA
直接利用Windows API提供的功能,更为直观。而HttpUrlSplitB
则通过手动解析,提供了更多的控制权。在实际项目中,选择取决于开发者对项目的要求和对代码控制的需求。
InternetCrackUrl
用于解析 URL。它将 URL 拆分为各个组成部分,例如协议、主机名、端口、路径等。这个函数的目的是方便开发者处理 URL,以便更容易地获取和使用其中的信息。
以下是关于 InternetCrackUrl
函数的一些关键信息:
BOOL InternetCrackUrl(_In_ PCTSTR lpszUrl,_In_ DWORD dwUrlLength,_In_ DWORD dwFlags,_Out_ LPURL_COMPONENTS lpUrlComponents
);
lpszUrl
: 指向包含 URL 字符串的空终止字符串的指针。dwUrlLength
: URL 字符串的长度,如果是 NULL 终止字符串,可以设置为DWORD(-1)
。dwFlags
: 一组标志,用于指定解析行为。lpUrlComponents
: 指向一个URL_COMPONENTS
结构体的指针,该结构体用于接收 URL 的各个组成部分。
URL_COMPONENTS
结构体包括以下字段:
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
: 结构体大小。lpszScheme
: 指向字符串的指针,该字符串包含 URL 的方案部分(如 “http”)。nScheme
: 表示 URL 方案的整数值。lpszHostName
: 指向字符串的指针,包含主机名部分。nPort
: 表示端口号。lpszUserName
和lpszPassword
: 分别是用户名和密码的部分。lpszUrlPath
: URL 路径部分。lpszExtraInfo
: 额外信息。
InternetCrackUrl
的返回值为 BOOL
类型,如果函数成功,返回非零值,否则返回零。函数成功后,lpUrlComponents
结构体中的字段将被填充。
这个函数通常用于在网络编程中处理 URL,例如在创建网络请求时提取主机名、端口和路径。
#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;// 通过InternetCrackUrl函数实现切割
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;
}
运行后则会对http://www.xxx.com/index.html
字符串进行路径切割,并输出主目录与子路径,如下图所示;
相对于使用原生API切割,自己实现也并不难,如下所示,通过_strnicmp
判断字符串长度并切割特定的位置,实现对字符串的切割;
#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;// 自己实现对URL路径的拆分
bool HttpUrlSplitB(const char* pszUrl)
{char szHost[256] = { 0 };char* ptr = (char*)pszUrl;// 判断开头是否为http:// 或者 https:// 如果不是则返回-1if (_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;
}
实现HTTP访问
HTTP 通常基于TCP(Transmission Control Protocol)。HTTP的本质是建立在底层的Socket通信之上的一种应用层协议。
概述HTTP访问的过程:
- 建立TCP连接: HTTP通信首先需要建立TCP连接,通常默认使用TCP的80端口。在建立连接之前,客户端和服务器需要通过DNS解析获取对应的IP地址。
- 发送HTTP请求: 客户端通过Socket向服务器发送HTTP请求,请求包括请求方法(GET、POST等)、URL路径、HTTP协议版本等信息。同时,客户端可以附带一些请求头(Headers)和请求体(Body),具体内容根据请求的性质而定。
- 服务器处理请求: 服务器接收到客户端的HTTP请求后,根据请求的内容进行处理。处理的方式取决于请求的方法,例如GET请求用于获取资源,POST请求用于提交数据等。服务器根据请求返回相应的HTTP响应。
- 发送HTTP响应: 服务器通过Socket向客户端发送HTTP响应,响应包括响应状态码、响应头和响应体。响应状态码表示服务器对请求的处理结果,例如200表示成功,404表示未找到资源,500表示服务器内部错误等。
- 关闭TCP连接: 一旦HTTP响应发送完毕,服务器关闭与客户端的TCP连接。客户端接收完响应后也可以关闭连接,或者继续发送其他请求。
整个HTTP访问的本质就是通过TCP连接在客户端和服务器之间传递HTTP请求和响应。Socket是负责实际数据传输的底层机制,而HTTP协议则定义了在这个基础上进行通信的规范。这种分层的设计使得不同的应用能够使用同一个底层的网络传输机制,提高了网络通信的灵活性和可扩展性。
通常实现HTTP访问与主机访问相同,唯一的区别是主机应用的访问遵循的是服务端的封包规则,而对于Web来说则需要遵循HTTP特有的访问规则,在Socket正式接收数据之前需要实现一个请求规范,也就是HTTP头部。
HTTP头部(HTTP headers)是HTTP请求和响应中的重要组成部分,它们包含了与请求或响应相关的信息。HTTP头部的格式通常是一个名值对(key-value pair)的集合,每个头部字段由一个字段名和一个字段值组成,它们以冒号分隔,例如:
HeaderName: HeaderValue
HTTP头部通常以回车符(Carriage Return,\r
)和换行符(Line Feed,\n
)的组合(\r\n
)结束,每个头部字段之间以\r\n
分隔。
以下是一些常见的HTTP头部字段及其示例:
- 通用头部(General Headers):
Cache-Control: no-cache
Date: Tue, 15 Nov 2022 08:12:31 GMT
Connection: keep-alive
- 请求头部(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
- 响应头部(Response Headers):
Content-Type: text/html; charset=utf-8
Content-Length: 12345
Server: Apache/2.4.41 (Unix)
- 实体头部(Entity Headers):
Content-Encoding: gzip
Last-Modified: Wed, 20 Oct 2022 12:00:00 GMT
Etag: "5f0a3e51-20"
HTTP头部的具体字段和含义可根据HTTP规范进行扩展,不同的应用场景和需求可能需要添加自定义的头部字段。这些头部字段在HTTP通信中起到了传递元信息、控制缓存、指定内容类型等作用。在代码中我们构建了一个如下所示的头部。
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);
在这个HTTP GET请求的基本格式,它包含了一些必要的头部信息。让我们逐行解释:
"GET %s HTTP/1.1 \r\n"
: 这表示使用HTTP协议的GET请求方式,%s
会被替换为实际的URL路径,HTTP版本为1.1。"Host: %s \r\n"
: 这里设置了HTTP请求的Host
头部,指定了服务器的主机名,%s
会被替换为实际的主机名。"User-Agent: Mozilla/5.0 (Windows NT 10.0) LyShark HttpGet 1.0 \r\n"
: 这是User-Agent
头部,它标识了发送请求的用户代理(即浏览器或其他客户端)。这里的字符串表示使用Mozilla浏览器5.0版本,运行在Windows NT 10.0操作系统上,LyShark HttpGet 1.0表示这个请求的自定义用户代理。"Accept-Type: */* \r\n"
: 这是Accept-Type
头部,表示客户端可以接受任意类型的响应内容。"Connection: Close \r\n\r\n"
:Connection
头部表示在完成请求后关闭连接,避免保持连接。\r\n\r\n
表示头部结束,之后是可选的请求体。
综合起来,这个HTTP GET请求的目的是获取指定URL路径的资源,请求头部包含了一些必要的信息,例如主机名、用户代理等。这是一个基本的HTTP请求格式,可以根据具体需求添加或修改头部信息。
#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;// 通过InternetCrackUrl函数实现切割
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方式访问页面
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;
}// 访问指定页面
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){// 获取所有网页内容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;
}
运行上述代码则会自动请求http://www.lyshark.com/index.html
路径的80
端口,以获取返回参数信息,如下图所示;
实现HTTPS访问
HTTPS的访问与HTTP基本类似,同样是通过Socket访问端口,同样是发送特定的GET请求头,唯一的不同在于当链接被建立后,对于HTTPS来说多出一个TLS协商的过程,这是为了保护传输时的安全而增加的安全特定,为了能实现访问我们需要使用OpenSSL库对完成TLS的握手才行。
OpenSSL 是一个强大的开源软件库,提供了一系列的密码学工具和库函数,广泛用于网络安全应用的开发。它支持许多密码学协议和算法,包括 SSL(Secure Sockets Layer)和 TLS(Transport Layer Security)协议,用于在计算机网络上实现安全通信。
HTTPS握手过程是建立在TLS(Transport Layer Security)协议之上的。TLS是SSL(Secure Sockets Layer)的继任者,用于在计算机网络上保障通信安全。以下是HTTPS握手的基本流程:
- 客户端Hello:
- 客户端向服务器发送
ClientHello
消息,其中包含支持的TLS版本、支持的加密算法、支持的压缩算法等信息。
- 客户端向服务器发送
- 服务器Hello:
- 服务器从客户端提供的信息中选择一个合适的TLS版本和加密套件,并向客户端发送
ServerHello
消息,同时发送服务器证书。
- 服务器从客户端提供的信息中选择一个合适的TLS版本和加密套件,并向客户端发送
- 认证:
- 客户端验证服务器发送的证书是否有效,通常包括证书的颁发机构(CA)的签名验证。客户端还可以验证证书中包含的域名是否匹配正在连接的域名。
- 密钥交换:
- 客户端生成一个随机值,使用服务器的公钥加密该随机值,然后将加密后的数据发送给服务器。服务器使用自己的私钥解密,得到客户端生成的随机值。这两个随机值将用于生成对话密钥。
- 对话密钥的生成:
- 客户端和服务器使用客户端生成的随机值、服务器生成的随机值以及前面协商的算法,通过一系列协商步骤生成对话密钥。
- 加密通信:
- 客户端和服务器使用生成的对话密钥对通信进行加密和解密,确保数据的隐私和完整性。
整个握手过程确保了通信双方的身份验证、密钥的安全协商以及通信内容的保密性和完整性。握手完成后,客户端和服务器使用协商得到的对话密钥进行加密通信,从而实现了安全的HTTPS连接。
如下所示代码以演示访问必应为例,需要获取必应的IP地址,以及在GET请求中更改访问域名为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库 创建SSL会话环境等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;// 发包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;
}
成勋运行后将会对必应发起https访问,并获取返回值信息,如下图所示;
相关文章:

C/C++ 发送与接收HTTP/S请求
HTTP(Hypertext Transfer Protocol)是一种用于传输超文本的协议。它是一种无状态的、应用层的协议,用于在计算机之间传输超文本文档,通常在 Web 浏览器和 Web 服务器之间进行数据通信。HTTP 是由互联网工程任务组(IETF…...
【算法集训】基础数据结构:一、顺序表(下)
由于今天的题目是昨天剩下的,所以只有两道题,也非常简单,刷完下班~~~嘿嘿 第六题 2656. K 个元素的最大和 https://leetcode.cn/problems/maximum-sum-with-exactly-k-elements/description/ 很简单的思路,要得到得分最大的&…...
[Java][项目][战斗逻辑]基于JFrame的文字游戏
项目注解: Core:启动文件 AttributeBean:玩家属性 BackpackedBean:背包设计(未完成) BackpackedFrame:背包页面(未完成) BattleField:战斗逻辑(核心&…...

顺序表和链表面试题
文章目录 顺序表(1)原地移除数组中所有的元素val,要求时间复杂度为O(N),空间复杂度为O(1)。(2)删除有序数组中的重复项(3)合并两个有序数组 链表(1)删除链表中等于给定值 val 的所有节点(2)反转一个单链表(3) 合并两个有序链表(4)链表的中间结点(5)链表中…...

树_二叉搜索树累加求和
//给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 // node.val 的值之和。 // // 提醒一下,二叉搜索树满足下列约束…...
gcc编译流程概述
前言 本篇文章介绍gcc编译器编译C文件的流程概述 比如我们创建了一个.c文件hello_gcc.c #include <stdio.h> int main() {printf("Hello gcc!!!\n");return 0; }最简单的方式就是在终端使用命令 gcc hello_gcc.c -o hello_gcc // 编译、汇编、链接 ./hello_…...

【web安全】ssrf漏洞的原理与使用
前言 菜某对ssrf漏洞的总结。 ssrf的作用 主要作用:访问外界无法访问的内网进行信息收集。 1.进行端口扫描,资源访问 2.指纹信息识别,访问相应的默认文件 3.利用漏洞或者和payload进一步运行其他程序 4.get类型漏洞利用,传参数…...

佳易王会员管理软件店铺积分以及积分兑换系统
一、佳易王会员管理软件大众版 部分功能简介: 1、会员信息登记 :可以直接使用手机号登记,也可以使用实体卡片,推荐用手机号即可。 2、会员卡类型 :可以自由设置卡的类型,比如:充值卡、计次卡、…...

Django回顾【二】
目录 一、Web框架 二、WSGI协议 三、 Django框架 1、MVC与MTV模型 2、Django的下载与使用 补充 3、启动django项目 补充 5、 Django请求生命周期 四、路由控制 1、路由是什么? 2、如何使用 3、path详细使用 4、re_path详细使用 5、反向解析 6、路由…...
[Ubuntu 18.04] RK3399搭建SSH服务实现远程访问
SSH(Secure Shell)是一种网络协议和软件,用于安全地远程登录到计算机并进行网络服务的加密通信。它提供了加密的认证和安全的数据传输,使得在不安全的网络中进行远程管理和访问变得更加安全。 以下是 SSH 服务的一些关键特点和用途: 安全认证:SSH 使用公钥/私钥加密技术…...

Linux进程间通信之共享内存
📟作者主页:慢热的陕西人 🌴专栏链接:Linux 📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言 本博客主要内容讲解共享内存原理和相关接口的介绍,以及一个…...

lv11 嵌入式开发 RTC 17
目录 1 RTC简介 编辑2 Exynos4412下的RTC控制器 2.1 概述 2.2 特征 2.3 功能框图 3 寄存器介绍 3.1 概述 3.2 BCD格式的年月日寄存器 3.3 INTP中断挂起寄存器 3.4 RTCCON控制寄存器 3.5 CURTICCNT 作为嘀嗒定时器使用的寄存器 4 RTC编程 5 练习 1 RTC简介 RTC(…...

c语言指针详解(上)
目录 一、指针的基本概念和用法 二、指针运算 2.1 指针的自增和自减运算 2.2 指针的自增和自减运算 三、数组和指针 四、指针和函数 4.1 在函数中使用指针作为参数和返回值 4.1.1 使用指针作为函数参数 4.1.2 使用指针作为函数返回值 4.2 指针参数的传值和传引用特性 4.2.1 指针…...

如何删除mac苹果电脑上面的流氓软件?
在使用苹果电脑的过程中,有时候我们也会遇到一些不需要的软件。无论是因为不再需要,或者是为了释放磁盘空间,删除这些软件是很重要的。本文将为大家介绍怎样删除苹果电脑上的软件! CleanMyMac X全新版下载如下: https://wm.make…...
WordPress(11)给文章添加预计阅读时长
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、文件配置二、代码块1.引入库2.配置 single.php三、效果图前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了…...
周周爱学习之快速排序
快速排序,顾名思义,快速排序是一种速度非常快的一种排序算法 平均时间复杂度为O(),最坏时间复杂度为O()数据量较大时,优势非常明显属于不稳定排序 1.算法描述 每一轮排序选择一个基准点(pivot)进行分区 让小于基准点…...

国产接口测试工具APIpost
说实话,了解APIpost是因为,我的所有接口相关的文章下,都有该APIpost水军的评论,无非就是APIpost是中文版的postman,有多么多么好用,虽然咱也还不是什么啥网红,但是不知会一声就乱在评论区打广告…...
MySQL电商管理系统练习题及答案
一 、表结构 用户表(user):id(主键)、username、password、email、phone、age商品表(product):id(主键)、name、price、stock、description订单表(order):id(主键)、user_id(外键,关联用户表)、total_price、status、create_time…...

每日3道PWN(第二天)
ciscn_2019_n_1 参考: [BUUCTF-pwn]——ciscn_2019_n_1-CSDN博客 [BUUCTF]PWN5——ciscn_2019_n_1_ciscn_2019_n_4-CSDN博客 BUUCTF—ciscn_2019_n_1 1-CSDN博客 checksec一下 64位栈溢出 按f5查看main函数,双击可疑函数 发现含有命令执行的且发现fl…...

SAP STMS传输请求
一、概述 一般SAP项目上都会有六套系统,分别是: 测试环境-DEV系统 主要由100:沙盘系统:用于业务顾问配置 200:开发系统:用于开发ABAP写代码 300:测试系统:主要是单元测试、顾问自己…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...