一个基本的http客户端
高可用 客户端
1. httpClient.h
#include <iostream>
#include <string>
#include <functional>class HttpClient
{
public:HttpClient(std::string url) : url_(url), port_(0) {}int write_http(const std::string &method, const std::string &msg);private:int get_socket();int set_sock_timeout(int sockfd, int sec, int ms);int set_buf_size(int sockfd, int sendsize, int recvsize);int domain_judge(const char *buf);int split_url(std::string &url, std::string &host, unsigned short &port);int host_get_by_name(const char *name);void print_netstat(int err);int noblock_connect(int sockfd, struct sockaddr *addrs, int addrlen);int make_http_head(const char *method, std::string &httpmsg, const std::string &purl);int make_http_msg(const std::string &method, std::string &msg);int writen(int connfd, const char *vptr, size_t n);int recvn_timeout(int connfd, char *vptr, int n, int timeout);std::string readn(int sockfd, size_t n);int parse_recvmsg(std::string &recvmsg);int parse_test(std::string &msg);private:std::function<int(std::string &)> parseFunc_;std::string url_;std::string host_;unsigned short port_;
};
2.httpClient.cpp
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <memory>#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/ioctl.h>#include <jsoncpp/json/json.h>#include "httpClient.h"int HttpClient::make_http_head(const char *method, std::string &httpmsg, const std::string &purl)
{char headbuf[1024] = {0};int len = snprintf(headbuf, sizeof(headbuf), "%s %s HTTP/1.1\r\n""Content-Type: application/json\r\n""Accept: application/json\r\n""Host: %s:%d\r\n""Connection: Keep-Alive\r\n""Content-Length: %d\r\n\r\n",method,purl.c_str(),host_.c_str(),port_,static_cast<int>(httpmsg.size()));httpmsg = headbuf + httpmsg;return 0;
}int HttpClient::make_http_msg(const std::string &method, std::string &msg)
{return make_http_head(method.c_str(), msg, "");
}int HttpClient::writen(int connfd, const char *vptr, size_t n)
{int nleft = n, nwrite = 0, retryCont = 0;char *ptr = const_cast<char *>(vptr);while (nleft > 0){if ((nwrite = send(connfd, ptr, nleft, MSG_NOSIGNAL)) <= 0){if (retryCont < 100 && (nwrite == 0 || errno == EINTR)){nwrite = 0;++retryCont;usleep(10000);}else{return -1;}}nleft -= nwrite;ptr += nwrite;}return n;
}int HttpClient::recvn_timeout(int connfd, char *vptr, int n, int sec)
{int nleft = n;int nread = 0, retryCnt = 0;char *ptr = vptr;fd_set fdset;struct timeval timeout;while (nleft > 0){timeout.tv_sec = sec;timeout.tv_usec = 0;FD_ZERO(&fdset);FD_SET(connfd, &fdset);if (select(connfd + 1, &fdset, nullptr, nullptr, &timeout) <= 0){printf("select fail errno = %d\n", errno);break;}if ((nread = recv(connfd, ptr, nleft, 0)) < 0){if (retryCnt < 50 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)){nread = 0;++retryCnt;usleep(10000);}else{break;}}else if (nread == 0){break;}nleft -= nread;ptr += nread;}return (n - nleft);
}std::string HttpClient::readn(int sockfd, size_t n)
{char buf[2048] = {0};std::string result;int total = 0;int byterecv;do{byterecv = recvn_timeout(sockfd, buf, 2048, 5);if (byterecv <= 0){break;}total += byterecv;result.append(buf, byterecv);} while (total < n && byterecv == sizeof(buf));return result;
}int HttpClient::parse_recvmsg(std::string &recvmsg)
{std::string ::size_type headend = recvmsg.find("\r\n\r\n");if (headend == std::string::npos){std::cout << "not found header" << std::endl;return false;}std::string body = recvmsg.substr(headend + 4);return parseFunc_(body);
}int HttpClient::split_url(std::string &url, std::string &host, unsigned short &port)
{if (!url.compare(0, 7, "http://")){url = url.substr(7);}if (!url.compare(0, 8, "https://")){url = url.substr(8);}size_t slashPos = url.find("/");if (slashPos != std::string::npos){url = url.substr(0, slashPos);}size_t colonPos = url.find(":");if (colonPos == std::string::npos){host = url;port = 80;}else{host = url.substr(0, colonPos);port = atoi(url.substr(colonPos + 1).c_str());}
}int HttpClient::domain_judge(const char *buf)
{if (nullptr == buf){return false;}bool hasChar = false, hasDot = false;for (size_t i = 0; i < strlen(buf); ++i){if (isalpha(buf[i])){hasChar = true;continue;}if ('.' == buf[i]){hasDot = true;continue;}if (hasChar && hasDot){return true;}}return false;
}int HttpClient::host_get_by_name(const char *name)
{// char ipaadress[64] = {0};struct addrinfo hints, *reslut = nullptr, *address = nullptr;memset(&hints, 0, sizeof(addrinfo));hints.ai_family = AF_UNSPEC; // ipv4 ipv6hints.ai_flags = AI_PASSIVE;hints.ai_socktype = SOCK_STREAM;int ret = getaddrinfo(name, nullptr, &hints, &reslut);if (ret != 0){std::cerr << "getaddrinfo err " << gai_strerror(ret) << std::endl;return ret;}for (address = reslut; address != nullptr; address = address->ai_next){if (address->ai_family == AF_INET){struct sockaddr_in *addr = reinterpret_cast<struct sockaddr_in *>(address->ai_addr);freeaddrinfo(reslut);return static_cast<int>(addr->sin_addr.s_addr);}else if (address->ai_family == AF_INET6){struct sockaddr_in6 *addr = reinterpret_cast<struct sockaddr_in6 *>(address->ai_addr);continue; // 暂不使用ipv6}}freeaddrinfo(reslut);return false;
}int HttpClient::set_buf_size(int sockfd, int sendsize, int recvsize)
{int ret1 = ::setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<char *>(&sendsize), sizeof(sendsize));int ret2 = ::setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<char *>(&recvsize), sizeof(recvsize));return (ret1 == 0 && ret2 == 0) ? 0 : -1;
}int HttpClient::set_sock_timeout(int sockfd, int sec, int ms)
{timeval timeout = {sec, ms * 1000};int ret1 = ::setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<char *>(&timeout), sizeof(timeout));int ret2 = ::setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast<char *>(&timeout), sizeof(timeout));return (ret1 == 0 && ret2 == 0) ? 0 : -1;
}int HttpClient::noblock_connect(int sockfd, struct sockaddr *addrs, int addrlen)
{struct timeval timeout = {5, 0};int err = -1;fd_set fdset;int flag = 1;if (ioctl(sockfd, FIONBIO, &flag) != 0){printf("ioctl error\n");}int ret = connect(sockfd, addrs, addrlen);if (-1 == ret){if (EINPROGRESS == errno){FD_ZERO(&fdset);FD_SET(sockfd, &fdset);if (select(sockfd + 1, nullptr, &fdset, nullptr, &timeout) > 0){getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, (socklen_t *)&addrlen);if (0 == err){ret = 0;}else{ret = -1;}}else{ret = -1;}}}flag = 0;if (ioctl(sockfd, FIONBIO, &flag) != 0){printf("ioctl error\n");}if (ret < 0){print_netstat(err);}return ret;
}void HttpClient::print_netstat(int err)
{switch (err){case ENETUNREACH: // 网不通case EHOSTUNREACH:printf("network is unreachable err[%d]\n", err);break;case ECONNREFUSED: // 连接端口被拒绝printf("no-one listening on the remote address\n");break;case ETIMEDOUT: // 网络连接失败,服务器未响应printf("timeout while attempting connection the server may be to busy\n");break;default:printf("other errno %d\n", err);break;}
}int HttpClient::get_socket()
{int bufsize = 0x20000; // 128kint errnoret = -1;struct sockaddr_in serveraddr;int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){return -1;}memset(&serveraddr, 0, sizeof(serveraddr));serveraddr.sin_family = AF_INET;split_url(url_, host_, port_);if (domain_judge(host_.c_str())){serveraddr.sin_addr.s_addr = host_get_by_name(host_.c_str());}else{serveraddr.sin_addr.s_addr = inet_addr(host_.c_str());}serveraddr.sin_port = htons(port_);if (set_buf_size(sockfd, bufsize, bufsize) < 0){close(sockfd);return -1;}if (set_sock_timeout(sockfd, 5, 0) < 0){close(sockfd);return -1;}int ret = noblock_connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));if (-1 == ret){close(sockfd);return -1;}return sockfd;
}int HttpClient::parse_test(std::string &msg)
{std::cout << msg << std::endl;return 0;
}int HttpClient::write_http(const std::string &method, const std::string &msg)
{std::string httpmsg = msg;int fd = get_socket();if (fd < 0){printf("fd is error\n");return -1;}make_http_msg(method, httpmsg);writen(fd, httpmsg.c_str(), httpmsg.size());std::string recvmsg = readn(fd, 2048);std::cout << recvmsg << std::endl;if (recvmsg.size()){parseFunc_ = std::bind(&HttpClient::parse_test, this, std::placeholders::_1);parse_recvmsg(recvmsg);}return 0;
}void test()
{HttpClient client("192.168.95.1:8080");client.write_http("post", "hello\n");
}int main()
{test();return 0;
}
相关文章:
一个基本的http客户端
高可用 客户端 1. httpClient.h #include <iostream> #include <string> #include <functional>class HttpClient { public:HttpClient(std::string url) : url_(url), port_(0) {}int write_http(const std::string &method, const std::string &…...
html-网站菜单-点击菜单展开相应的导航栏,加减号可切换
一、效果图 1.点击显示菜单栏,点击x号关闭; 2.点击一级菜单,展开显示二级,并且加号变为减号; 3.点击其他一级导航,自动收起展开的导航。 二、代码实现 <!DOCTYPE html> <html><head>&…...
2.FastRunner定时任务Celery+RabbitMQ
注意:celery版本和Python冲突问题 不能用高版本Python 用3.5以下,因为项目的celery用的django-celery 3.2.2 python3.7 async关键字 冲突版本 celery3.x方案一: celery3.xpython3.6方案二 : celery4.xpython3.7 解决celery执…...
vb.net 实时监控双门双向门禁控制板源代码
本示例使用设备介绍:实时网络双门双向门禁控制板可二次编程控制网络继电器远程开关-淘宝网 (taobao.com) Imports System.Net.Sockets Imports System.Net Imports System.Text Imports System.ThreadingImports System.Net.NetworkInformation Imports System.Man…...
文具办公产品展示预约小程序的作用如何
从整体来看,文具办公品牌/门店的生意来源于线下自然流量或线上自营商城/入驻第三方商城的的流量,线上多数情况都是以直接销售配送为主,但其实对文具品牌/门店而言还有信息展示、服务预约、在线咨询、产品介绍等需求。 虽然小区周边的消费者需…...
渗透测试流程是什么?7个步骤给你讲清楚!
在学习渗透测试之初,有必要先系统了解一下它的流程,静下心来阅读一下,树立一个全局观,一步一步去建设并完善自己的专业领域,最终实现从懵逼到牛逼的华丽转变。渗透测试是通过模拟恶意黑客的攻击方法,同时也…...
如何解决网站被攻击的问题:企业网络攻防的关键路径
在当今数字化时代,企业面临着不断升级的网络威胁,网站遭受攻击的风险也与日俱增。解决网站被攻击的问题对企业发展至关重要,不仅关系到企业的信息安全,也直接影响到企业的声誉和利益。从企业发展的角度出发,我们将探讨…...
大健康产业的先行者「完美公司」携手企企通,推进企业采购供应链数字化进程
随着中国经济持续向好,消费升级和美妆步骤增加,美妆和个人护理产品已逐渐成为中国消费者的日用消费品,推动了护肤品和化妆品的销售额增速均超过10%,成为中国整个快速消费品市场中的一颗亮眼明珠。 据国家统计局数据显示࿰…...
在windows Server安装Let‘s Encrypt的SSL证书
1、到官网(https://certbot.eff.org/instructions?wswebproduct&oswindows)下载 certbot客户端。 2、安装客户端(全部默认安装即可) 3、暂停IIS中的网站 开始菜单中找到并运行“Certbot”,输入指令: …...
GPT实战系列-P-Tuning本地化训练ChatGLM2等LLM模型,到底做了什么?(二)
GPT实战系列-如何使用P-Tuning本地化训练ChatGLM2等LLM模型?(二) 文章目录 GPT实战系列-1.训练参数配置传递2.训练前准备3.训练参数配置4.训练对象,seq2seq训练5.执行训练6.训练模型评估依赖数据集的预处理 P-Tuning v2 将 ChatGLM2-6B 模型需要微调的参…...
Python3.7+PyQt5 pyuic5将.ui文件转换为.py文件、Python读取配置文件、生成日志
1.实际开发项目时,是使用Qt Designer来设计UI界面,得到一个.ui的文件,然后利用PyQt5安装时自带的工具pyuic5将.ui文件转换为.py文件: pyuic5 -o mywindow.py mywindow.ui #先是py文件名,再是ui文件名样式图 QT5 UI&am…...
使用 VPN ,一定要知道的几个真相!
你们好,我的网工朋友。 今天想和你聊聊VPN。在VPN出现之前,企业分支之间的数据传输只能依靠现有物理网络(例如Internet)。 但由于Internet中存在多种不安全因素,报文容易被网络中的黑客窃取或篡改,最终造…...
数电实验-----实现74LS153芯片扩展为8选1时间选择器以及应用(Quartus II )
目录 一、74LS153芯片介绍 管脚图 功能表 二、4选1选择器扩展为8选1选择器 1.扩展原理 2.电路图连接(Quartus II ) 3.仿真结果 三、8选1选择器的应用 1.三变量表决器 2.奇偶校验电路 一、74LS153芯片介绍 74ls153芯片是属于四选一选择器的芯片。…...
如何实现MATLAB与Simulink的数据交互
参考链接:如何实现MATLAB与Simulink的数据交互 MATLAB是一款强大的数学计算软件,Simulink则是一种基于模型的多域仿真平台,常用于工程和科学领域中的系统设计、控制设计和信号处理等方面。MATLAB和Simulink都是MathWorks公司的产品࿰…...
【数据结构】归并排序
👦个人主页:Weraphael ✍🏻作者简介:目前正在学习c和算法 ✈️专栏:数据结构 🐋 希望大家多多支持,咱一起进步!😁 如果文章有啥瑕疵 希望大佬指点一二 如果文章对你…...
数字引领,智慧赋能|袋鼠云与易知微共同亮相2023智慧港口大会
2023年10月19日,由中国港口协会、中国交通通信信息中心、天津港(集团)有限公司主办,中国港口协会智慧港口专业委员会、《港口科技》杂志社等单位承办的以“数字引领 智慧赋能”为主题的“2023智慧港口大会”在天津顺利召开。 袋鼠…...
星火模型(Spark)的langchain 实现
星火模型的langchain实现 测试已通过,希望有所帮助。 使用前请先安装环境: pip install githttps://github.com/shell-nlp/spark-ai-python.git注意: 一定要使用上面方式安装spark库,因对官方的库做了改动。官方的库已经长时间不…...
python运算符重载之构造函数和迭代器
1 python运算符重载之构造函数和迭代器 python运算符重载是在类方法中拦截内置操作-当类的实例使用内置操作时,pytho自动调用对应方法,并且返回操作结果。 NO#描述1拦截运算运算符重载拦截内置操作,比如打印、函数调用、点号运算、表达式运…...
【数据处理】Python:实现求条件分布函数 | 求平均值方差和协方差 | 求函数函数期望值的函数 | 概率论
猛戳订阅! 👉 《一起玩蛇》🐍 💭 写在前面:本章我们将通过 Python 手动实现条件分布函数的计算,实现求平均值,方差和协方差函数,实现求函数期望值的函数。部署的测试代码放到文后了,运行所需环境 python version >= 3.6,numpy >= 1.15,nltk >= 3.4,tqd…...
new/delete 和malloc/free的区别
C中: 创建单个数据空间: char *ch new char; delete ch; ch NULL; 创建多个数据空间: char *ch new char[4]; delete [] ch; ch NULL; C语言中: 创建单个数据空间: char *ch malloc(sizeof(char)); fre…...
从Java转行大模型应用,Advanced-RAG 学习
一、RAG 进阶概述(Advanced-RAG)基础RAG(检索增强生成)核心是“检索生成”的两阶段流程,解决大模型“幻觉”和知识时效性问题,但在复杂场景(长文档、模糊查询、高精准需求)中存在检索…...
PDF文本高效提取:用pdftotext实现秒级文档内容解析
PDF文本高效提取:用pdftotext实现秒级文档内容解析 【免费下载链接】pdftotext Simple PDF text extraction 项目地址: https://gitcode.com/gh_mirrors/pd/pdftotext 破解PDF提取痛点:为什么你需要专业工具? 每天面对数十份PDF文档却…...
Fish Speech 1.5开源大模型落地:为乡村学校定制方言普通话双语教学语音
Fish Speech 1.5开源大模型落地:为乡村学校定制方言普通话双语教学语音 想象一下,在偏远山区的教室里,孩子们正跟着一个亲切的“本地老师”学习普通话。这位老师不仅能说一口标准的普通话,还能用孩子们熟悉的家乡方言进行解释和互…...
告别手动维护!用DataX-Web搞定MySQL到ClickHouse的增量同步(含时间戳配置)
高效构建MySQL到ClickHouse的增量同步管道:DataX-Web实战指南 在数据驱动的商业环境中,企业每天都会产生海量的业务数据。这些数据通常存储在OLTP系统如MySQL中,但为了进行分析和报表生成,我们需要将这些数据同步到OLTP系统如Clic…...
给STM32密码锁加个“记忆”:手把手教你用CubeMX配置I2C读写EEPROM(AT24C02)
为STM32密码锁赋予持久记忆:CubeMX驱动AT24C02 EEPROM全攻略 当你的密码锁在断电后依然能记住最后一次设置的密码,这种"记忆"能力往往能大幅提升用户体验。本文将带你深入探索如何通过I2C总线连接AT24C02 EEPROM芯片,为基于STM32F1…...
BilibiliDown视频下载全攻略:从效率瓶颈到批量管理的进阶之路
BilibiliDown视频下载全攻略:从效率瓶颈到批量管理的进阶之路 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mi…...
Matlab与VeriStand无缝集成:开发环境配置全攻略
1. 环境准备:软件安装与版本匹配 搞过Matlab和VeriStand集成的朋友都知道,最头疼的不是写代码,而是环境配置。我当年第一次尝试时,光软件版本兼容性问题就折腾了两天。这里分享几个血泪教训: 首先Matlab和VeriStand的版…...
告别“瞎测”:如何用Tessent ATPG生成高效测试向量(Pattern)提升芯片良率
芯片测试效率革命:Tessent ATPG实战指南与良率提升策略 在半导体行业,每一纳秒的测试时间缩减都可能转化为数百万美元的成本节约。当芯片设计进入7nm以下工艺节点时,制造缺陷导致的良率问题愈发突出,传统测试方法已无法满足现代芯…...
Matlab APP Designer避坑指南:字符进度条不更新的解决方案
Matlab APP Designer避坑指南:字符进度条不更新的解决方案 在Matlab APP Designer开发过程中,进度条是用户交互体验的重要组成部分。许多开发者都遇到过这样的困扰:精心设计的字符进度条在运行时却"卡住"不动,直到整个计…...
Qwen3-TTS-12Hz-1.7B-Base真实案例:为视障开发者生成无障碍编程教程语音
Qwen3-TTS-12Hz-1.7B-Base真实案例:为视障开发者生成无障碍编程教程语音 1. 这不是“读出来就行”的语音,而是真正听得懂代码的语音助手 你有没有想过,一段Python函数说明、一个React组件生命周期图解、甚至一段带缩进和符号的JSON结构&…...
