Http协议封装
Myhttp封装http协议
源代码
#include <iostream>
#include <cstring>
#include <string>
#include <thread>
#include <atomic>
#include <fstream> // 添加文件操作头文件#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
typedef int socklen_t;
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h> // 包含 inet_pton 函数
#define closesocket close
#endifstruct hostent *AutoGetIp(std::string domain, std::string &target_ip)
{struct hostent *host = gethostbyname(domain.c_str());if (host == nullptr){std::cerr << "Get IP address error for domain: " << domain << std::endl;return nullptr;}std::cout << "Initialized domain to IP: " << host->h_name;if (host->h_addr_list[0]){target_ip = inet_ntoa(*(struct in_addr *)host->h_addr_list[0]); // 将域名返回的可用ip列表第一个赋值给ipstd::cout << " --> " << target_ip << std::endl;}return host;
}class HttpRequest
{
private:int client_fd = -1;std::atomic<bool> stopListening{false};public:struct hostent *host; // 主机结构体std::string domain;std::string ip;int ip_version = AF_INET; // 默认使用ipv4int port = 80; // 默认http协议是80端口HttpRequest() : host(nullptr) {}HttpRequest(std::string domain_) : HttpRequest(domain_, 80) {}HttpRequest(std::string domain_, int port_) : domain(domain_), port(port_){std::string target_ip;host = AutoGetIp(domain, target_ip);if (host == nullptr){std::cerr << "Failed to get IP address for domain: " << domain << std::endl;return;}ip = target_ip;ip_version = host->h_addrtype;std::string ip_str = ip_version == AF_INET ? "IPv4" : "IPv6";std::cout << "IP version: " << ip_str << std::endl;}HttpRequest(std::string ip_, int ip_v, int port_) : ip(ip_), ip_version(ip_v), port(port_) // 如果只知道ip和ip协议的版本{struct in_addr addr; // ipv4地址结构体if (inet_pton(ip_version, ip.c_str(), &addr) <= 0){std::cerr << "Invalid address/ Address not supported." << std::endl;return;}host = gethostbyaddr((const char *)&addr, sizeof(addr), ip_version);if (host == nullptr){std::cerr << "Get host by address error for IP: " << ip << std::endl;return;}domain = host->h_name;printf("Hostname: %s\n", host->h_name);}~HttpRequest(){stopListening = true;if (client_fd != -1){closesocket(client_fd);}
#ifdef _WIN32WSACleanup();
#endif}void setIP(std::string ip_) { ip = ip_; }void setPort(int port_) { port = port_; }int connect_to(){
#ifdef _WIN32WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){std::cerr << "Failed to initialize Winsock." << std::endl;return -1;}
#endifclient_fd = socket(ip_version, SOCK_STREAM, 0);if (client_fd == INVALID_SOCKET){std::cerr << "Socket creation failed." << std::endl;
#ifdef _WIN32WSACleanup();
#endifreturn -1;}struct sockaddr_in server_address;server_address.sin_family = AF_INET; // 使用 IPv4 协议server_address.sin_port = htons(port);if (inet_pton(ip_version, ip.c_str(), &server_address.sin_addr) <= 0){std::cerr << "Invalid address/ Address not supported." << std::endl;closesocket(client_fd);
#ifdef _WIN32WSACleanup();
#endifreturn -1;}if (connect(client_fd, (struct sockaddr *)&server_address, sizeof(server_address)) < 0){std::cerr << "Connection failed." << std::endl;closesocket(client_fd);
#ifdef _WIN32WSACleanup();
#endifreturn -1;}std::cout << "Connected to server." << std::endl;sendContent();std::ofstream outFile("server_response.txt", std::ios::app); // 创建或打开文件以追加内容if (!outFile.is_open()){std::cerr << "Failed to open file for writing." << std::endl;return -1;}std::cout << "File opened successfully: server_response.txt" << std::endl;std::thread t([this, &outFile](){char buffer[1024] = {0};std::cout << "Listening for msg" << std::endl;while (!stopListening){int valread = recv(client_fd, buffer, sizeof(buffer) - 1, 0);if (valread < 0){std::cerr << "Receive failed." << std::endl;break;}else if (valread == 0){std::cout << "Connection closed by server." << std::endl;break;}else{buffer[valread] = '\0';std::cout << "Received message from server: " << buffer << std::endl;outFile << buffer; // 将接收到的数据写入文件}memset(buffer, 0, sizeof(buffer));}outFile.close(); // 关闭文件std::cout << "File closed successfully: server_response.txt" << std::endl;closesocket(client_fd); });t.join();#ifdef _WIN32WSACleanup();
#endifreturn 0;}void sendContent(){std::string msg = "GET / HTTP/1.1\r\nHost: " + domain + "\r\nConnection: Close\r\n\r\n";int result = send(client_fd, msg.c_str(), msg.length(), 0);if (result < 0){std::cerr << "Send failed." << std::endl;}else{std::cout << "Successfully sent " << result << " bytes\n";}}
};int main()
{
#ifdef _WIN32WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){std::cerr << "Failed to initialize Winsock." << std::endl;return -1;}
#endifHttpRequest httprequest("www.baidu.com", 80);httprequest.connect_to();#ifdef _WIN32WSACleanup();
#endifreturn 0;
}
API函数
gethostbyname()
gethostbyname
函数用于通过域名或主机名获取其对应的IP地址信息。它返回一个指向hostent
结构体的指针,该结构体包含了主机的相关信息。
gethostbyname
函数原型
#include <netdb.h>
struct hostent *gethostbyname(const char *name);
hostent
结构体内容
hostent
结构体定义如下:
struct hostent {char *h_name; // 官方主机名char **h_aliases; // 主机别名列表int h_addrtype; // 地址类型(如AF_INET表示IPv4)int h_length; // 地址长度char **h_addr_list; // 地址列表
};
- h_name:官方主机名。例如,
www.baidu.com
的官方主机名可能是www.a.shifen.com
。 - h_aliases:主机的别名列表。一个主机可以有多个别名,这些别名也用于访问该主机。
- h_addrtype:地址类型,通常为
AF_INET
表示IPv4地址。 - h_length:地址长度,IPv4地址长度为4字节。
- h_addr_list:地址列表,包含了主机的所有IP地址。对于IPv4地址,可以使用
inet_ntoa
函数将其转换为点分十进制格式。
工作原理
gethostbyname
首先检查本地的/etc/hosts
文件,如果找到匹配的主机名,则返回相应的IP地址。- 如果未在
hosts
文件中找到匹配项,它会向DNS服务器发送查询请求,以获取主机名对应的IP地址。
注意事项
gethostbyname
只能返回IPv4地址。如果需要获取IPv6地址或同时获取IPv4和IPv6地址,应使用getaddrinfo
函数。- 返回的
hostent
结构体的内存由系统管理,因此在使用完毕后不需要手动释放。
gethostbyaddr()
在Linux系统中,将IP地址转换成域名(即反向DNS解析)可以使用gethostbyaddr
函数。这个函数是POSIX标准的一部分,用于根据IP地址查找对应的主机名。以下是关于gethostbyaddr
函数的详细说明和使用示例:
函数原型
#include <netdb.h>
struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type);
参数说明
- addr:指向IP地址的指针。对于IPv4地址,应该是一个指向
struct in_addr
的指针;对于IPv6地址,应该是一个指向struct in6_addr
的指针。 - len:地址的长度。对于IPv4地址,长度为
sizeof(struct in_addr)
;对于IPv6地址,长度为sizeof(struct in6_addr)
。 - type:地址类型,可以是
AF_INET
(IPv4)或AF_INET6
(IPv6)。
返回值
- 成功时返回指向
hostent
结构体的指针,该结构体包含了主机的相关信息。 - 失败时返回
NULL
,可以通过h_errno
获取错误原因(例如使用herror
函数)。
示例代码
以下是一个使用gethostbyaddr
函数进行反向DNS解析的示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>int main() {struct in_addr ip_addr;struct hostent *host;// 示例IP地址inet_pton(AF_INET, "8.8.8.8", &ip_addr);// 执行反向DNS解析host = gethostbyaddr(&ip_addr, sizeof(ip_addr), AF_INET);if (host == NULL) {herror("gethostbyaddr failed");return EXIT_FAILURE;}// 输出主机名printf("Hostname: %s\n", host->h_name);return EXIT_SUCCESS;
}
注意事项
- 在使用
gethostbyaddr
之前,确保系统中已经配置了DNS服务器,并且DNS服务器能够响应反向查询请求。 gethostbyaddr
函数可能不是线程安全的,如果需要在多线程环境中使用,可以考虑使用getaddrinfo
函数的反向解析功能。
inet_ntoa()
-
功能:将IPv4地址的网络字节序二进制形式转换为点分十进制的字符串表示形式。
-
参数:
struct in_addr in
:包含IPv4地址的in_addr
结构体。
-
返回值:
- 返回指向转换后的字符串的指针。该字符串是静态分配的,因此每次调用
inet_ntoa
都会覆盖上一次的结果
- 返回指向转换后的字符串的指针。该字符串是静态分配的,因此每次调用
-
注意事项
inet_ntoa
只支持IPv4地址,且返回的字符串是静态分配的,因此在多线程环境中使用时需要特别注意。- 对于IPv6地址或需要线程安全的场景,推荐使用
inet_pton
和inet_ntop
。
struct in_addr ip_addr;
inet_pton(AF_INET, "192.168.1.1", &ip_addr);
char *ip_str = inet_ntoa(ip_addr);
printf("IP address: %s\n", ip_str);
inet_ntop()
- 功能:将IP地址的网络字节序二进制形式转换为字符串表示形式。
- 参数:
int af
:地址族,可以是AF_INET
(IPv4)或AF_INET6
(IPv6)。const void *src
:指向二进制IP地址的指针。char *dst
:指向用于存储转换后的字符串的缓冲区的指针。socklen_t size
:缓冲区的大小。
- 返回值:
- 成功时返回指向
dst
的指针。 - 失败时返回
NULL
。
- 成功时返回指向
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>int main() {struct in_addr ip_addr;inet_pton(AF_INET, "192.168.1.1", &ip_addr);char ip_str[INET_ADDRSTRLEN];const char *result = inet_ntop(AF_INET, &ip_addr, ip_str, INET_ADDRSTRLEN);if (result == NULL) {perror("inet_ntop");exit(EXIT_FAILURE);}printf("IP address in string format: %s\n", ip_str);return 0;
}
inet_pton()
- 功能:将IP地址的字符串表示形式转换为网络字节序的二进制形式。
- 参数:
int af
:地址族,可以是AF_INET
(IPv4)或AF_INET6
(IPv6)。const char *src
:指向IP地址字符串的指针。void *dst
:指向存储转换后的二进制地址的缓冲区的指针。
- 返回值:
- 成功时返回1。
- 输入字符串无效时返回0。
- 出错时返回-1。
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>int main() {struct in_addr ip_addr;int result = inet_pton(AF_INET, "192.168.1.1", &ip_addr);if (result != 1) {perror("inet_pton");exit(EXIT_FAILURE);}printf("IP address in binary format: %u.%u.%u.%u\n",(unsigned char)ip_addr.s_addr,(unsigned char)(ip_addr.s_addr >> 8),(unsigned char)(ip_addr.s_addr >> 16),(unsigned char)(ip_addr.s_addr >> 24));return 0;
}
相关文章:
Http协议封装
Myhttp封装http协议 源代码 #include <iostream> #include <cstring> #include <string> #include <thread> #include <atomic> #include <fstream> // 添加文件操作头文件#ifdef _WIN32 #include <winsock2.h> #include <ws2t…...

el-date-picker 禁用一个月前、一个月后(当天之后)的时间 datetimerange
文章目录 功能需求今天是 2025-01-09示例1示例2 代码 Vue2 功能需求 时间范围选择器,最大时间选择尺度为一个月。 今天是 2025-01-09 示例1 选择 2025-01-02 日 禁用未来日期(2025-01-09之后日期) 禁用上月2号(31日之前&#…...

【C】编译与链接
在本文章里面,我们讲会讲解C语言程序是如何从我们写的代码一步步变成计算机可以执行的二进制指令,并最终执行的。C语言程序运行主要包括两大步骤 -- 编译和链接,接下来我们就来一一讲解。 目录 1 翻译环境和运行环境 2 翻译环境 1&#…...

Github上传项目
写在前面: 本次博客仅仅是个人学习记录,不具备教学作用。内容整理来自网络,太多了,所以就不放来源了。 在github页面的准备: 输入标题。 往下滑,创建 创建后会跳出下面的页面 进入home就可以看到我们刚…...
webrtc之rtc::ArrayView<const uint8_t>
rtc::ArrayView<const uint8_t> 是 WebRTC(或其他基于 rtc 命名空间的库)中常见的一个类型,它通常用于表示一块 只读的内存区域,该内存区域由一系列 uint8_t 类型(无符号 8 位整数)元素组成。 1. rt…...

Zemax 序列模式下的扩束器
扩束器结构原理 扩束器用于增加准直光束(例如激光束)的直径,同时保持其准直。它通常用于激光光学和其他需要修改光束大小或发散度的应用。 在典型的扩束器中,输入光束是准直激光器,或光束进入第一个光学元件。当光束开…...

Flink系统知识讲解之:如何识别反压的源头
Flink系统知识之:如何识别反压的源头 什么是反压 Ufuk Celebi 在一篇古老但仍然准确的文章中对此做了很好的解释。如果您不熟悉这个概念,强烈推荐您阅读这篇文章。如果想更深入、更低层次地了解该主题以及 Flink 网络协议栈的工作原理,这里有…...

RK3568平台(USB篇)禁用USB端口
一.linux中怎样查看usb的端口号 在USB口插入U盘: [ 198.141319][ T106] usb 3-1.3: new SuperSpeed Gen 1 USB device number 5 using xhci-hcd [ 198.161695][ T106] usb 3-1.3: New USB device found, idVendor=0781, idProduct=5591, bcdDevice= 1.00 [ 198.161721]…...
洛谷 P3000 [USACO10DEC] Cow Calisthenics G
思路 题目要求断若干条边后形成的连通块中,最大的直径最小,很明显的二分。关键就在于如何写 c h e c k check check 函数了。 可以用 d f s dfs dfs 来判断要断哪条边。 一、 d [ u ] d[u] d[u] 定义 设 d [ u ] d[u] d[u] 为从 u u u 出发到子树…...

Web渗透测试之XSS跨站脚本攻击 盲打 详解
目录 XSS盲打 什么是盲打: 盲打主要目的 XSS盲打 什么是盲打: 发现某个页面有xss漏洞 但是注入后没看到效果 而是在其它页面进行xss显示的效果 这种就叫盲打. 我注册了一个网站的用户 注册页面存在xss漏洞跳转到首页 看不到注册信息的输出 当管理员打开页面查看什么用户…...
经典编程题:服务器广播
题目描述: 服务器连接方式包括直接相连,间接连接。A 和 B 直接连接,B 和 C 直接连接,则 A 和 C 间接连接。直接连接和间接连接都可以发送广播。 给出一个 N*N 数组,代表 N 个服务器,matrix[i][j]1…...

【网络协议】静态路由详解
网络中的路由器通过以下两种方式之一发现远程网络: 静态配置路由动态路由协议 在本文,我们将学习关于静态路由的各种概念,例如如何配置静态路由、路由表如何进行决策、路由接口等相关知识。 文章目录 引言直连网络静态路由路由表原则原则1原…...

朝天椒USB服务器在银泰证券虚拟化超融合场景的应用案例
在数字化浪潮席卷金融行业的今天,银泰证券作为业内知名的金融机构,始终致力于提升业务运营效率与数据安全性。面对虚拟化超融合场景下各种认证U盾的管理挑战,银泰证券选择了朝天椒USB服务器作为其解决方案,成功实现了U盾在虚拟机中…...

.NET framework、Core和Standard都是什么?
对于这些概念一直没有深入去理解,以至于经过.net这几年的发展进化,概念越来越多,越来越梳理不容易理解了。内心深处存在思想上的懒惰,以为自己专注于Unity开发就好,这些并不属于核心范畴,所以对这些概念总是…...

FairGuard游戏安全2024年度报告
导 读:2024年,国内游戏市场实际销售收入3257.83亿元,同比增长7.53%,游戏用户规模6.74亿人,同比增长0.94%,市场收入与用户规模双双实现突破,迎来了历史新高点。但游戏黑灰产规模也在迅速扩大&…...
JetBrains IDEs和Visual Studio Code的对比
JetBrains IDEs和Visual Studio Code的对比 JetBrains IDEs是捷克JetBrains公司开发的一系列集成开发环境(IDE)。以下是具体介绍:IntelliJ IDEA是JetBrains 公司的一款产品 主要产品 IntelliJ IDEA:一款功能强大且广泛应用的Java集成开发环境,有开源免费的社区版和商业收…...

文件剪切走:深度解析与高效恢复策略
一、文件剪切走现象解读 在计算机的日常使用中,“文件剪切走”这一术语形象地描述了文件在移动过程中意外丢失的现象。当用户尝试将文件从一个位置“剪切”并粘贴到另一个位置时,如果操作不当或系统出现异常,可能会导致文件在源位置消失&…...

Win32汇编学习笔记09.SEH和反调试
Win32汇编学习笔记09.SEH和反调试-C/C基础-断点社区-专业的老牌游戏安全技术交流社区 - BpSend.net SEH - structed exception handler 结构化异常处理 跟筛选一样都是用来处理异常的,但不同的是 筛选器是整个进程最终处理异常的函数,但无法做到比较精细的去处理异常(例如处理…...
[人工智能]CSDN创作助手体验
一、什么是智能体 智能体是一种能够感知环境、学习、推理和行动的实体。它可以是一个计算机程序、机器人或其他类似的系统。智能体的目标是通过与环境的交互来实现特定的任务或目标。 智能体通常由以下几个组件组成: 感知器:感知器是智能体与环境之间的…...

vue3中el-table实现多表头并表格合并行或列
1、el-table中添加事件 :span-method"genderSpanCity" <el-table :span-method"genderSpanCity":data"data.tableData":fit"true" table-layout"fixed" header-align"center" stripestyle"width:100%;he…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...

Excel 怎么让透视表以正常Excel表格形式显示
目录 1、创建数据透视表 2、设计 》报表布局 》以表格形式显示 3、设计 》分类汇总 》不显示分类汇总 1、创建数据透视表 2、设计 》报表布局 》以表格形式显示 3、设计 》分类汇总 》不显示分类汇总...