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…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...
保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...
QT开发技术【ffmpeg + QAudioOutput】音乐播放器
一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下,音视频内容犹如璀璨繁星,点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频,到在线课堂中知识渊博的专家授课,再到影视平台上扣人心弦的高清大片,音…...
智警杯备赛--excel模块
数据透视与图表制作 创建步骤 创建 1.在Excel的插入或者数据标签页下找到数据透视表的按钮 2.将数据放进“请选择单元格区域“中,点击确定 这是最终结果,但是由于环境启不了,这里用的是自己的excel,真实的环境中的excel根据实训…...
