C++ 实现HTTP的客户端、服务端demo和HTTP三方库介绍

        本文使用C++模拟实现http的客户端请求和http的服务端响应功能,并介绍几种封装HTTP协议的三方库。

1、实现简单HTTP的服务端功能

        本程序使用C++ tcp服务端代码模拟HTTP的服务端,服务端返回给客户端的消息内容按照HTTP协议的消息响应格式进行了组装。

demo如下:

#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>int main() {int server_fd, new_socket;struct sockaddr_in address;int addrlen = sizeof(address);char buffer[1024] = {0};const char* hello = "HTTP/1.1 200 OK\nContent-Type: text/plain\n\nHello, World!";// 创建套接字if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("socket failed");exit(EXIT_FAILURE);}address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons(37777);// 绑定套接字到端口if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {perror("bind failed");exit(EXIT_FAILURE);}// 监听连接if (listen(server_fd, 3) < 0) {perror("listen");exit(EXIT_FAILURE);}printf("Listening on port 37777\n");while (true) {if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {perror("accept");exit(EXIT_FAILURE);}// 读取客户端请求int length = read(new_socket, buffer, 1024);printf("******** HTTP Server recv request length: %d,as follow: ********\n%s\n",length,buffer);// 发送响应send(new_socket, hello, strlen(hello), 0);printf("******** HTTP Server replied to the request ********\n");close(new_socket);}return 0;
}

2、实现简单HTTP的客户端功能

         本程序使用C++ tcp客户端代码模拟HTTP的客户端,客户端发给服务端的请求内容按照HTTP协议的请求格式进行了组装。

demo如下:

#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>int main() {int sock = 0, length;struct sockaddr_in serv_addr;char buffer[1024] = {0};const char* get_request = "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n";if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {perror("Socket creation error");exit(EXIT_FAILURE);}serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(37777);//serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //bind ip method 1// 将IPv4地址从点分十进制转换为二进制形式 bind ip method 2if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {perror("Invalid address/Address not supported");exit(EXIT_FAILURE);}if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {perror("Connection failed");exit(EXIT_FAILURE);}send(sock, get_request, strlen(get_request), 0);printf("HTTP Client GET method has been sent\n");length = read(sock, buffer, 1024);printf("******** HTTP Client receive msg length: %d,context as follow: ********\n%s\n",length,buffer);printf("****************\n");close(sock);return 0;
}

分别运行上面的服务端和客户端程序,服务端程序运行结果如下:

客户端程序运行结果如下:

 3、实现HTTP的客户端访问百度功能

        本程序使用C++ tcp客户端代码模拟HTTP的客户端,按照http协议请求格式对百度网页进行GET请求消息的组装。

实现demo如下:

#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>#define URL  "/"                            //资源
#define HTTP_VESTION "HTTP/1.1"
#define HOST "www.baidu.com"                //域名
#define	CONNETION  "Connection: close\r\n"  //短链接
#define BUFFER_SIZE		1024
std::string strBuffer = "";
int getIpAddress(char** ip)
{int ret = -1;struct  hostent *ht = NULL;ht = gethostbyname(HOST);if(ht) {printf("type:%s\n", ht->h_addrtype == AF_INET ? "AF_INET" : "AF_INET6");for(int i=0; ;i++) {if(ht->h_addr_list[i]!=NULL) {*ip = inet_ntoa(*((struct in_addr *)ht->h_addr_list[i]));ret = 1;break;}}}return ret;
}char* receiveNew(int sockfd, size_t& len) {char* buffer = nullptr; // 初始化为nullptrssize_t totalBytesReceived = 0; // 累计接收的字节数ssize_t bytesReceived; // 当前接收的字节数// 循环接收数据,直到对方关闭连接或发生错误do {// 分配额外的空间以容纳更多数据char* newBuffer = new char[totalBytesReceived + 1024]; // 假设每次额外分配1024字节,用于接受下次数据if (buffer) {// 如果有旧的数据,复制到新的缓冲区,每次所有内容复制一遍std::memcpy(newBuffer, buffer, totalBytesReceived);delete[] buffer; // 释放旧缓冲区}buffer = newBuffer; // 更新指针以指向新的缓冲区,指向的内容可以任意大,即只要可分配// 接收数据bytesReceived = recv(sockfd, buffer + totalBytesReceived, 1024, 0);if (bytesReceived == -1) {// 错误处理,例如检查errnostd::cerr << "Error receiving data: " << strerror(errno) << std::endl;delete[] buffer; // 释放已分配的缓冲区return nullptr; // 返回nullptr表示错误}totalBytesReceived += bytesReceived; // 累计已接收的字节数// 如果需要,可以在此处设置接收的最大字节数限制} while (bytesReceived > 0); // 当recv返回0时,表示对方已关闭连接// 调整缓冲区的大小以匹配实际接收的数据量char* finalBuffer = new char[totalBytesReceived + 1]; // +1为了字符串终止符'\0'std::memcpy(finalBuffer, buffer, totalBytesReceived);finalBuffer[totalBytesReceived] = '\0'; // 添加字符串终止符delete[] buffer; // 释放中间缓冲区len = totalBytesReceived; // 更新len以反映实际接收的数据长度return finalBuffer; // 返回最终缓冲区
}void receiveString(int sockfd, size_t& len) {char buffer[BUFFER_SIZE] = {}; // 初始化为nullptrssize_t totalBytesReceived = 0; // 累计接收的字节数ssize_t bytesReceived; // 当前接收的字节数// 循环接收数据,直到对方关闭连接或发生错误do {// 接收数据bytesReceived = recv(sockfd, buffer, BUFFER_SIZE, 0);if (bytesReceived == -1) {// 错误处理,例如检查errnoprintf("Error receiving data:%s", strerror(errno));}strBuffer += buffer;totalBytesReceived += bytesReceived; // 累计已接收的字节数memset(buffer,0,BUFFER_SIZE);// 如果需要,可以在此处设置接收的最大字节数限制} while (bytesReceived > 0); // 当recv返回0时,表示对方已关闭连接len = totalBytesReceived;
}void MakeSocketConnect()
{char* ipAddr = nullptr;getIpAddress(&ipAddr);int sock = 0;struct sockaddr_in serv_addr;serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(80);if (inet_pton(AF_INET, ipAddr, &serv_addr.sin_addr) <= 0) {perror("Invalid address/Address not supported");exit(EXIT_FAILURE);}if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {perror("Socket creation error");exit(EXIT_FAILURE);}if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {perror("Connection failed");exit(EXIT_FAILURE);}char get_request[1024] = {};sprintf(get_request,"GET %s %s\r\n""Host: %s\r\n""%s\r\n""\r\n",URL,HTTP_VESTION,HOST,CONNETION);send(sock, get_request, strlen(get_request), 0);printf("HTTP Client GET method has been sent\n");size_t len = 0; // 用于保存接收到的数据的长度/* 由于HTTP服务端回复的消息客户端一次接收不完,需要多次接收,直到数据接收完毕*  本文采用下面两种C++方法进行接收*  方法1:采用new方法分配内存,缺点:需要多次分配,并且需要多次memcpy(可以使用c语言malloc分配内存,realloc扩容)*  方法2:采用string容器(stinrg是字符串容器),动态的存储数据,也可以采用vector<char>容器存储*/
#if 0char* receivedData = receiveNew(sock,len);if (receivedData) {// 处理接收到的数据printf("******** HTTP Client receive msg length: %d,context as follow: ********\n%s\n",len,receivedData);printf("****************\n");// 释放动态分配的内存delete[] receivedData;} else {// 错误处理printf("Failed to receive data.\n");}
#elsereceiveString(sock,len);printf("******** HTTP Client receive msg length: %d,context as follow: ********\n%s\n",len,strBuffer.c_str());printf("****************\n");
#endifclose(sock);
}int main() {MakeSocketConnect();return 0;
}

上面程序运行结果如下:

上面接收的响应正文太长,上面图片没有截完。

C++ 实现http请求用法也可参考下面的文章:Linux C/C++ 实现HTTP请求器(TCP客户端)_linux c++ http-CSDN博客

4、HTTP协议的三方库

        使用封装HTTP协议的三方库,可以高效开发HTTP的功能需求,HTTP的协议封装有很多的三方库,下面只介绍几种,更多的三方库可查看其他资料。

(1)cpp-httplib

       优点:

                轻量级:非常轻量,仅包含一个头文件,方便集成到项目中。

                简单易用:API设计直观,可以快速上手。

                跨平台:支持多种操作系统,如Windows、Linux和macOS等。

                支持断点续传:通过ETag和Range字段,可以实现断点续传功能。

        缺点:

                功能相对简单:相比于其他HTTP库,可能不支持一些高级特性。

(2)libcurl

         优点:

                功能强大:支持多种协议,包括HTTP、HTTPS、FTP等。

                灵活性强:支持代理、HTTP POST、SSL连接、HTTP PUT等多种功能。

                跨平台:可以在多种操作系统上运行。

                与其他库配合:可以与其他网络库如libevent、openssl等配合使用,实现高性能的网络

                 编程。

         缺点:

                依赖外部库:需要安装和配置libcurl库。

        libcurl的介绍和使用可参考libcurl开源库的编译与使用全攻略_libcurl编译-CSDN博客

(3)Poco C++ Libraries

         优点:

                功能丰富:除了HTTP功能外,还包含其他实用程序库,如日志记录、XML解析等。

                跨平台:支持多种操作系统和编译器。

                稳定性:经过长时间的验证和广泛的使用,具有较高的稳定性。

         缺点:

                较为庞大:包含多个库和模块,可能对于只需要HTTP功能的项目来说过于庞大。

        cpp-httplib适合需要轻量级、简单易用且跨平台的HTTP库的项目。 libcurl适合需要强大功能和灵活性的项目,特别是需要支持多种协议和与其他库配合使用的场景。Poco C++ Libraries适合需要丰富功能和稳定性的大型项目。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/354890.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Apipost模拟HTTP客户端

目录 APIFOX的站内下载&#xff1a; Apipost模拟HTTP客户端&#xff08;正文&#xff09; 新建窗口 添加服务器地址、头信息介绍 添加请求体 发送以及返回状态 模拟HTTP客户端的软件有很多&#xff0c;其中比较著名的就有API-FOX、POSTMAN。 相信很多小伙伴都使用POSTMAN…

Maya 2024 mac/win版:创意无界,设计新生

Maya 2024是一款由Autodesk推出的业界领先的三维计算机图形软件&#xff0c;广泛应用于电影、游戏、广告等创意产业。这款软件以其强大的功能和卓越的性能&#xff0c;为艺术家们提供了一个实现创意梦想的平台。 Maya 2024 mac/win版获取 在建模方面&#xff0c;Maya 2024提供…

Flutter 自定义日志模块设计

前言 村里的老人常说&#xff1a;“工程未动&#xff0c;日志先行。” 有效的利用日志&#xff0c;能够显著提高开发/debug效率&#xff0c;否则程序运行出现问题时可能需要花费大量的时间去定位错误位置和出错原因。 然而一个复杂的项目往往需要打印日志的地方比较多&#…

YOLOv10改进 | Conv篇 |YOLOv10引入SPD-Conv卷积

1. SPD-Conv介绍 1.1 摘要:卷积神经网络(CNN)在图像分类和目标检测等许多计算机视觉任务中取得了巨大的成功。 然而,在图像分辨率较低或物体较小的更艰巨的任务中,它们的性能会迅速下降。 在本文中,我们指出,这源于现有 CNN 架构中一个有缺陷但常见的设计,即使用跨步卷…

【github】项目的代码仓库重命名

问题 有时候&#xff0c;我们先创建了远端项目仓库&#xff0c;然后就把相关code上传到远端项目仓库。 可能需要结合实际情况对远端项目仓库进行重命名。 当前仓库名称v_ttc&#xff0c;如何将他修改成v_datejs 操作步骤 1、在 GitHub.com 上&#xff0c;导航到存储库的主页…

【云原生】Kubernetes----Metrics-Server组件与HPA资源

目录 引言 一、概述 &#xff08;一&#xff09;Metrics-Server简介 &#xff08;二&#xff09;Metrics-Server的工作原理 &#xff08;三&#xff09;HPA与Metrics-Server的作用 &#xff08;四&#xff09;HPA与Metrics-Server的关系 &#xff08;五&#xff09;HPA与…

java面向对象(上)

一.面向对象与面向过程 1.面向过程 面向过程(procedure Oriented Programming),简称POP,主要思想就是将问题分解成一个个步骤去解决,把这个步骤称为函数. 典型语言:C语言 优点:可以大大简化代码 缺点:当代码量过大时,不方便维护 2.面向对象 面向对象(Object Oriented Pr…

【C语言】手写学生管理系统丨附源码+教程

最近感觉大家好多在忙C语言课设~ 我来贡献一下&#xff0c;如果对你有帮助的话谢谢大家的点赞收藏喔&#xff01; 1. 项目分析 小白的神级项目&#xff0c;99%的程序员&#xff0c;都做过这个项目&#xff01; 掌握这个项目&#xff0c;就基本掌握 C 语言了&#xff01; 跳…

口袋中有红、黄、蓝、白、黑5种颜色的球若干。每次从口袋中任意取出3个球,问得到3种不同颜色的球的可能取法,输出每种排列的情况

如果一个变量只能有几种可能的值&#xff0c;可以定义为枚举&#xff08;enumeration&#xff09;类型。所谓"枚举"是指将变量的值一一列举出来&#xff0c;变量的值只能在列举出来的值的范围内。 声明枚举类型用enum开头。例如&#xff1a; enum weekday{su…

Matlab个性化绘图第3期—带三维球标记的折线图

前段时间有会员在群里问该如何绘制下面这种带三维球标记的折线图&#xff1a; 本期内容就来分享一下带三维球标记的折线图的Matlab绘制思路。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源群中&#xff0c;加群的朋友请自行下载。有需…

Navicat和SQLynx功能比较三(数据导出:使用MySQL近千万数据测试)

数据导出的功能在数据库管理工具中是最普遍的功能之一。所以数据导出的功能稳定性和性能也是数据库管理工具是否能很好地满足应用需求的一个考虑因素。 目录 1. 整体比较 2. 示例 2.1 前置环境 2.2 Navicat导出 2.3 SQLynx导出 2.4 性能对比结果&#xff08;690万行数据&…

【机器学习】线性回归:从基础到实践的深度解析

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 线性回归&#xff1a;从基础到实践的深度解析引言一、线性回归基础1.1 定义与目…

浸没式液冷服务器的换热效率及节能潜力分析

服务器浸没式液冷的换热效率及节能潜力 摘要&#xff1a;我们针对服务器浸没式液冷实验台进行了深入测试&#xff0c;探究了不同室外温度和服务器发热功率对系统制冷PUE的影响。实验数据显示&#xff0c;该系统的制冷PUE值介于1.05至1.28之间&#xff0c;高效节能特点显著。 在…

Java代码如何运行

通过前面的第一篇文章&#xff0c;对JVM整体脉络有了一个大概了解。第二篇文章我们通过对高级语言低级语言不同特性的探讨引出了Java的编译过程。有了前面的铺垫&#xff0c;咱们今天正式进入Java到底是如何运行起来的探讨。 目前大部分公司都是使用maven作为包管理工具&#x…

大润发超市购物卡怎么用?

收到大润发超市的礼品卡以后&#xff0c;我才发现&#xff0c;最近的大润发也得十来公里 为了100块的大润发打车也太不划算了 叫外送也不在配送范围内 最后没办法&#xff0c;在收卡云上出掉了&#xff0c;还好最近价格不错&#xff0c;也不亏&#xff0c;收卡云的到账速度也…

Jmeter 性能测试步骤是什么?

性能测试是软件开发过程中非常重要的一环。它可以帮助我们评估软件系统在不同负载下的性能表现&#xff0c;找出系统中的性能瓶颈&#xff0c;并提供改进方案。而JMeter作为一款功能强大且广泛使用的性能测试工具&#xff0c;可以帮助我们实现这一目标。 下面&#xff0c;我将…

【机器学习】从理论到实践:决策树算法在机器学习中的应用与实现

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 目录 &#x1f4d5;引言 ⛓决策树的基本原理 1. 决策树的结构 2. 信息增益 熵的计算公式 信息增益的计算公式 3. 基尼指数 4. 决策树的构建 &#x1f916;决策树的代码实现 1. 数据准备 2. 决策树模型训练 3.…

XMind 2024软件最新版下载及详细安装教程

​人所共知的是XMind 在公司和教育领域都有很广泛的应用&#xff0c;在公司中它能够用来进行会议管理、项目管理、信息管理、计划和XMind 被认为是一种新一代演示软件的模式。也就是说XMind不仅能够绘制思维导图&#xff0c;还能够绘制鱼骨图、二维图、树形图、逻辑图、组织结构…

记一次某单位的内网渗透测试

0x01 web打点 访问漏洞url:http://www.xx.xx.com进入某医疗系统 使用越权加文件上传拿到shell 0x02 内网渗透 192.168.xx.x 管理员 通过哥斯拉上线msf 上线后进行信息收集: 网卡信息、补丁信息、杀毒进程、用户在线情况、是否存在域、翻文件查找数据库密码、浏览器保存密码…

【ai】tx2-nx:搭配torch的torchvision

微雪的教程pytorch_version 1.10.0 官方教程安装torch官方教程 依赖项 nvidia@tx2-nx:~/twork/03_yolov5$ $ sudo apt-get install libjpeg-dev zlib1g-dev lib