2403C++,C++20协程库

原文

基于C++20协程的http--cinatra

cinatra是基于C++20无栈协程实现的跨平台,仅头,高性能,易用的http/https(http1.1),包括httpserverhttpclient,功能完备,不仅支持最普通的getpost等请求,还支持restfulapi,websocket,chunked,ranges,multipart,静态文件服务和反向代理等功能.

后面会分别介绍这些功能,文末也专门附上benchmark测试代码.

2.基本http请求

2.1.启动http服务器

#include <include/cinatra.hpp>
using namespace cinatra;
void start_server() {coro_http_server server(/*`thread_num=`*/std::thread::hardware_concurrency(), 9001);server.set_http_handler<GET>("/", [](coro_http_request &req, coro_http_response &resp) {resp.set_status_and_content(status_type::ok, "ok"); //`IO`线程中的响应});server.set_http_handler<GET, POST>("/in_thread_pool",[](coro_http_request &req,coro_http_response &resp) -> async_simple::coro::Lazy<void> {//在线程池中休息.co_await coro_io::post([&] {resp.set_status_and_content(status_type::ok, "ok in thread pool");});});server.sync_start();
}

几行代码即可创建一个http服务,先设置httpserver工作线程数和端口.然后设置http服务的url,httpmethod和对应的处理函数.
可在io线程或线程池中处理http请求.

2.2.client发请求

#include <include/cinatra.hpp>
using namespace cinatra;
async_simple::coro::Lazy<void> do_request() {coro_http_client client{};auto result = co_await client.async_get("http://127.0.0.1:9001/");assert(result.status == 200);assert(result.resp_body == "ok");for (auto [key, val] : result.resp_headers) {std::cout << key << ": " << val << "\n";}result = co_await client.async_get("/in_thread_pool");assert(result.status == 200);
}

httpclient异步请求服务器,返回结果中包括服务端响应的状态码,httpcontenthttp头,如果网络错误,可从result.net_err中取错码和错误message.

2.3.restfulapi

  coro_http_server server(/*`thread_num=`*/std::thread::hardware_concurrency(), 9001);server.set_http_handler<cinatra::GET, cinatra::POST>("/test2/{}/test3/{}",[](coro_http_request &req,coro_http_response &resp) -> async_simple::coro::Lazy<void> {co_await coro_io::post([&]() {CHECK(req.matches_.str(1) == "name");CHECK(req.matches_.str(2) == "test");resp.set_status_and_content(cinatra::status_type::ok, "hello world");});co_return;});server.set_http_handler<cinatra::GET, cinatra::POST>(R"(/numbers/(\d+)/test/(\d+))",[](coro_http_request &req, coro_http_response &response) {CHECK(req.matches_.str(1) == "100");CHECK(req.matches_.str(2) == "200");response.set_status_and_content(status_type::ok, "number regex ok");});server.set_http_handler<cinatra::GET, cinatra::POST>("/user/:id", [](coro_http_request &req, coro_http_response &response) {CHECK(req.params_["id"] == "cinatra");response.set_status_and_content(status_type::ok, "ok");});server.set_http_handler<cinatra::GET, cinatra::POST>("/user/:id/subscriptions",[](coro_http_request &req, coro_http_response &response) {CHECK(req.params_["id"] == "subid");response.set_status_and_content(status_type::ok, "ok");});server.set_http_handler<cinatra::GET, cinatra::POST>("/values/:x/:y/:z",[](coro_http_request &req, coro_http_response &response) {CHECK(req.params_["x"] == "guilliman");CHECK(req.params_["y"] == "cawl");CHECK(req.params_["z"] == "yvraine");response.set_status_and_content(status_type::ok, "ok");});server.async_start();coro_http_client client;client.get("http://127.0.0.1:9001/test2/name/test3/test");client.get("http://127.0.0.1:9001/numbers/100/test/200");client.get("http://127.0.0.1:9001/user/cinatra");client.get("http://127.0.0.1:9001/user/subid/subscriptions");client.get("http://127.0.0.1:9001/value/guilliman/cawl/yvraine");

2.4. https访问

#ifdef CINATRA_ENABLE_SSLcoro_http_client client{};result = co_await client.async_get("https://www.taobao.com");assert(result.status == 200);
#endif

访问https网站时,确保已安装了openssl并开启了ENABLE_SSL.

3. websocket

  cinatra::coro_http_server server(1, 9001);server.set_http_handler<cinatra::GET>("/ws_echo",[](cinatra::coro_http_request &req,cinatra::coro_http_response &resp) -> async_simple::coro::Lazy<void> {cinatra::websocket_result result{};while (true) {result = co_await req.get_conn()->read_websocket();if (result.ec) {break;}if (result.type == cinatra::ws_frame_type::WS_CLOSE_FRAME) {REQUIRE(result.data == "test close");break;}auto ec = co_await req.get_conn()->write_websocket(result.data);if (ec) {break;}}});server.sync_start();

在协程处理函数中,while循环异步读写websocket数据.

client端:

  cinatra::coro_http_client client{};std::string message(100, 'x');client.on_ws_close([](std::string_view reason) {std::cout << "web socket close " << reason << std::endl;});client.on_ws_msg([message](cinatra::resp_data data) {if (data.net_err) {std::cout << "ws_msg net error " << data.net_err.message() << "\n";return;}std::cout << "ws msg len: " << data.resp_body.size() << std::endl;REQUIRE(data.resp_body == message);});co_await client.async_ws_connect("ws://127.0.0.1:9001/ws_echo");co_await client.async_send_ws(message);co_await client.async_send_ws_close("test close");

client设置读回调和close回调分别处理收到的websocket消息和websocketclose消息.

4.静态文件服务

  std::string filename = "temp.txt";create_file(filename, 64);coro_http_server server(1, 9001);std::string virtual_path = "download";std::string files_root_path = "";  //当前路径server.set_static_res_dir(virtual_path,files_root_path);//在服务器启动之前设置此项,如果添加新文件,则需要重启服务器.server.async_start();coro_http_client client{};auto result =co_await client.async_get("http://127.0.0.1:9001/download/temp.txt");assert(result.status == 200);assert(result.resp_body.size() == 64);

服务端设置虚路径和实际文件路径,下载文件时输入虚路径实际路径下的文件名即可实现下载.

5.反向代理

假设有3个服务器需要代理,代理服务器根据负载均衡算法来选择其中的一个来访问并把结果返回给客户.

5.1.先启动3个被代理的服务器

  cinatra::coro_http_server web_one(1, 9001);web_one.set_http_handler<cinatra::GET, cinatra::POST>("/",[](coro_http_request &req,coro_http_response &response) -> async_simple::coro::Lazy<void> {co_await coro_io::post([&]() {response.set_status_and_content(status_type::ok, "web1");});});web_one.async_start();cinatra::coro_http_server web_two(1, 9002);web_two.set_http_handler<cinatra::GET, cinatra::POST>("/",[](coro_http_request &req,coro_http_response &response) -> async_simple::coro::Lazy<void> {co_await coro_io::post([&]() {response.set_status_and_content(status_type::ok, "web2");});});web_two.async_start();cinatra::coro_http_server web_three(1, 9003);web_three.set_http_handler<cinatra::GET, cinatra::POST>("/", [](coro_http_request &req, coro_http_response &response) {response.set_status_and_content(status_type::ok, "web3");});web_three.async_start();

5.2.启动代理服务器

设置roundrobin策略的代理服务器:

  coro_http_server proxy_rr(2, 8091);proxy_rr.set_http_proxy_handler<GET, POST>("/rr", {"127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"},coro_io::load_blance_algorithm::RR);proxy_rr.sync_start();

设置random策略的代理服务器:

  coro_http_server proxy_random(2, 8092);proxy_random.set_http_proxy_handler<GET, POST>("/random", {"127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"});proxy_random.sync_start();

设置weightroundrobin策略的代理服务器:

  coro_http_server proxy_wrr(2, 8090);proxy_wrr.set_http_proxy_handler<GET, POST>("/wrr", {"127.0.0.1:9001", "127.0.0.1:9002", "127.0.0.1:9003"},coro_io::load_blance_algorithm::WRR, {10, 5, 5});proxy_wrr.sync_start();  

5.3.client请求代理服务器

  coro_http_client client_rr;resp_data resp_rr = client_rr.get("http://127.0.0.1:8091/rr");assert(resp_rr.resp_body == "web1");resp_rr = client_rr.get("http://127.0.0.1:8091/rr");assert(resp_rr.resp_body == "web2");resp_rr = client_rr.get("http://127.0.0.1:8091/rr");assert(resp_rr.resp_body == "web3");coro_http_client client_wrr;resp_data resp = client_wrr.get("http://127.0.0.1:8090/wrr");assert(resp.resp_body == "web1");resp = client_wrr.get("http://127.0.0.1:8090/wrr");assert(resp.resp_body == "web1");resp = client_wrr.get("http://127.0.0.1:8090/wrr");assert(resp.resp_body == "web2");resp = client_wrr.get("http://127.0.0.1:8090/wrr");assert(resp.resp_body == "web3");  

6.增加切面

6.1.创建任意切面

struct log_t {bool before(coro_http_request &, coro_http_response &) {std::cout << "before log" << std::endl;return true;}bool after(coro_http_request &, coro_http_response &res) {std::cout << "after log" << std::endl;res.add_header("aaaa", "bbcc");return true;}
};
struct get_data {bool before(coro_http_request &req, coro_http_response &res) {req.set_aspect_data("hello world");return true;}
};

切面是实现了beforeafter函数的类.

6.2.应用切面

async_simple::coro::Lazy<void> use_aspects() {coro_http_server server(1, 9001);server.set_http_handler<GET>("/get",[](coro_http_request &req, coro_http_response &resp) {auto val = req.get_aspect_data();assert(val[0] == "hello world");resp.set_status_and_content(status_type::ok, "ok");},log_t{}, get_data{});//设置了两个切面,可按需设置任意个切面server.async_start();coro_http_client client{};auto result = co_await client.async_get("http://127.0.0.1:9001/get");assert(result.status == 200);
}

注册httphandler时设置了两个切面,该url的处理会先进入切面,切面返回true,才会继续往下执行业务逻辑,如果返回false则不会执行后续逻辑,返回false时,要在切面中调用resp.set_status_and_content设置状态码返回内容.

7.chunked,ranges,multipart

7.1.chunked上传下载

chunked协议适合大文件上传和下载:

async_simple::coro::Lazy<void> chunked_upload_download() {coro_http_server server(1, 9001);server.set_http_handler<GET, POST>("/chunked",[](coro_http_request &req,coro_http_response &resp) -> async_simple::coro::Lazy<void> {assert(req.get_content_type() == content_type::chunked);chunked_result result{};std::string content;while (true) {result = co_await req.get_conn()->read_chunked();if (result.ec) {co_return;}if (result.eof) {break;}content.append(result.data);}std::cout << "content size: " << content.size() << "\n";std::cout << content << "\n";resp.set_format_type(format_type::chunked);resp.set_status_and_content(status_type::ok, "chunked ok");});server.set_http_handler<GET, POST>("/write_chunked",[](coro_http_request &req,coro_http_response &resp) -> async_simple::coro::Lazy<void> {resp.set_format_type(format_type::chunked);bool ok;if (ok = co_await resp.get_conn()->begin_chunked(); !ok) {co_return;}std::vector<std::string> vec{"hello", " world", " ok"};for (auto &str : vec) {if (ok = co_await resp.get_conn()->write_chunked(str); !ok) {co_return;}}ok = co_await resp.get_conn()->end_chunked();});server.sync_start();result = co_await client.async_get("http://127.0.0.1:9001/write_chunked");assert(result.status == 200);assert(result.resp_body == "hello world ok");
}

clientchunked上传文件

coro_http_client client{};std::string filename = "test.txt";create_file(filename, 1010);coro_io::coro_file file{};co_await file.async_open(filename, coro_io::flags::read_only);std::string buf;detail::resize(buf, 100);auto fn = [&file, &buf]() -> async_simple::coro::Lazy<read_result> {auto [ec, size] = co_await file.async_read(buf.data(), buf.size());co_return read_result{buf, file.eof(), ec};};auto result = co_await client.async_upload_chunked("http://127.0.0.1:9001/chunked"sv, http_method::POST, std::move(fn));

client读文件分块上传文件整个过程都是异步的.

clientchunked下载文件:

  auto result = co_await client.async_get("http://127.0.0.1:9001/write_chunked");assert(result.status == 200);assert(result.resp_body == "hello world ok");

这样下载内存中,也可下载文件中.

  auto result = co_await client.async_download("http://127.0.0.1:9001/write_chunked", "download.txt");CHECK(std::filesystem::file_size("download.txt")==1010);

7.2.ranges下载

async_simple::coro::Lazy<void> byte_ranges_download() {create_file("test_multiple_range.txt", 64);coro_http_server server(1, 8090);server.set_static_res_dir("", "");server.async_start();std::this_thread::sleep_for(200ms);std::string uri = "http://127.0.0.1:8090/test_multiple_range.txt";{std::string filename = "test1.txt";std::error_code ec{};std::filesystem::remove(filename, ec);coro_http_client client{};resp_data result = co_await client.async_download(uri, filename, "1-10");assert(result.status == 206);assert(std::filesystem::file_size(filename) == 10);filename = "test2.txt";std::filesystem::remove(filename, ec);result = co_await client.async_download(uri, filename, "10-15");assert(result.status == 206);assert(std::filesystem::file_size(filename) == 6);}{coro_http_client client{};std::string uri = "http://127.0.0.1:8090/test_multiple_range.txt";client.add_header("Range", "bytes=1-10,20-30");auto result = co_await client.async_get(uri);assert(result.status == 206);assert(result.resp_body.size() == 21);std::string filename = "test_ranges.txt";client.add_header("Range", "bytes=0-10,21-30");result = co_await client.async_download(uri, filename);assert(result.status == 206);assert(fs::file_size(filename) == 21);}
}

7.3.multipart上传下载

  coro_http_server server(1, 8090);server.set_http_handler<cinatra::PUT, cinatra::POST>("/multipart_upload",[](coro_http_request &req,coro_http_response &resp) -> async_simple::coro::Lazy<void> {assert(req.get_content_type() == content_type::multipart);auto boundary = req.get_boundary();multipart_reader_t multipart(req.get_conn());while (true) {auto part_head = co_await multipart.read_part_head();if (part_head.ec) {co_return;}std::cout << part_head.name << "\n";std::cout << part_head.filename << "\n";std::shared_ptr<coro_io::coro_file> file;std::string filename;if (!part_head.filename.empty()) {file = std::make_shared<coro_io::coro_file>();filename = std::to_string(std::chrono::system_clock::now().time_since_epoch().count());size_t pos = part_head.filename.rfind('.');if (pos != std::string::npos) {auto extent = part_head.filename.substr(pos);filename += extent;}std::cout << filename << "\n";co_await file->async_open(filename, coro_io::flags::create_write);if (!file->is_open()) {resp.set_status_and_content(status_type::internal_server_error, "file open failed");co_return;}}auto part_body = co_await multipart.read_part_body(boundary);if (part_body.ec) {co_return;}if (!filename.empty()) {auto ec = co_await file->async_write(part_body.data.data(), part_body.data.size());if (ec) {co_return;}file->close();CHECK(fs::file_size(filename) == 1024);}else {std::cout << part_body.data << "\n";}if (part_body.eof) {break;}}resp.set_status_and_content(status_type::ok, "ok");co_return;});server.async_start();std::string filename = "test_1024.txt";create_file(filename);coro_http_client client{};std::string uri = "http://127.0.0.1:8090/multipart_upload";client.add_str_part("test", "test value");client.add_file_part("test file", filename);auto result =async_simple::coro::syncAwait(client.async_upload_multipart(uri));CHECK(result.status == 200);

8.benchmarkcode

8.1. brpc http benchmark code
DEFINE_int32(port, 9001, "TCP Port of this server");
DEFINE_int32(idle_timeout_s, -1,"Connection will be closed if there is no ""read/write operations during the last `idle_timeout_s'");
class HttpServiceImpl : public HttpService {
public:HttpServiceImpl() {}virtual ~HttpServiceImpl() {}void Echo(google::protobuf::RpcController *cntl_base, const HttpRequest *,HttpResponse *, google::protobuf::Closure *done) {brpc::ClosureGuard done_guard(done);brpc::Controller *cntl = static_cast<brpc::Controller *>(cntl_base);std::string date_str{get_gmt_time_str()};cntl->http_response().SetHeader("Date", date_str);cntl->http_response().SetHeader("Server", "brpc");cntl->http_response().set_content_type("text/plain");butil::IOBufBuilder os;os << "hello, world!";os.move_to(cntl->response_attachment());}
};
int main(int argc, char *argv[]) {GFLAGS_NS::ParseCommandLineFlags(&argc, &argv, true);brpc::Server server;example::HttpServiceImpl http_svc;if (server.AddService(&http_svc, brpc::SERVER_DOESNT_OWN_SERVICE) != 0) {LOG(ERROR) << "Fail to add http_svc";return -1;}brpc::ServerOptions options;options.idle_timeout_sec = FLAGS_idle_timeout_s;if (server.Start(FLAGS_port, &options) != 0) {LOG(ERROR) << "Fail to start HttpServer";return -1;}server.RunUntilAskedToQuit();return 0;
}

8.2.drogonbenchmarkcode

#include <drogon/drogon.h>
using namespace drogon;
int main() {app().setLogPath("./").setLogLevel(trantor::Logger::kWarn).addListener("0.0.0.0", 9001).setThreadNum(0).registerSyncAdvice([](const HttpRequestPtr &req) -> HttpResponsePtr {auto response = HttpResponse::newHttpResponse();response->setBody("Hello, world!");return response;}).run();
}

8.3.nginxhttp配置

user nginx;
worker_processes auto;
worker_cpu_affinity auto;
error_log stderr error;
#worker_rlimit_nofile 1024000;
timer_resolution 1s;
daemon off;
events {worker_connections 32768;multi_accept off; #default
}
http {include /etc/nginx/mime.types;access_log off;server_tokens off;msie_padding off;sendfile off; #defaulttcp_nopush off; #defaulttcp_nodelay on; #defaultkeepalive_timeout 65;keepalive_disable none; #default msie6keepalive_requests 300000; #default 100server {listen 9001 default_server reuseport deferred fastopen=4096;root /;location = /plaintext {default_type text/plain;return 200 "Hello, World!";}}
}

8.4.cinatrabenchmarkcode

#include <cinatra.hpp>
using namespace cinatra;
using namespace std::chrono_literals;
int main() {coro_http_server server(std::thread::hardware_concurrency(), 8090);server.set_http_handler<GET>("/plaintext", [](coro_http_request& req, coro_http_response& resp) {resp.get_conn()->set_multi_buf(false);resp.set_content_type<resp_content_type::txt>();resp.set_status_and_content(status_type::ok, "Hello, world!");});server.sync_start();
}

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

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

相关文章

Python程序的流程

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 年轻是我们唯一拥有权利去编制梦想的时…

【前端素材】推荐优质后台管理系统Annex平台模板(附源码)

一、需求分析 1、系统定义 后台管理系统是一种用于管理网站、应用程序或系统的管理界面&#xff0c;通常由管理员和工作人员使用。它提供了访问和控制网站或应用程序后台功能的工具和界面&#xff0c;使其能够管理用户、内容、数据和其他各种功能。 2、功能需求 后台管理系…

利用python爬取本站的所有博客链接

目录 前因 首先的尝试 解决办法 导入包 定义一个json配置文件 打开浏览器执行操作 注意 提取源代码并且进行筛选链接 执行结果 前因 由于自己要把csdn的博客同步到hugo中&#xff0c;把博客转为md格式已经搞好了&#xff0c;但是由于csdn的图片具有防盗链&#xff0c;…

vue实现商品评分效果(通过插件实现)

Vue.js 实现了一个简单的商品评分功能。用户可以通过点击星星来修改商品的评分&#xff0c;并且评分显示了相应的星星数。 废话不多说&#xff0c;直接上代码 方法一&#xff1a; <template><div><avue-form :model"formData"><avue-form-it…

2024年经典【自动化面试题】附答案

一、请描述一下自动化测试流程&#xff1f; 自动化测试流程一般可以分为以下七步&#xff1a; 编写自动化测试计划&#xff1b; 设计自动化测试用例&#xff1b; 编写自动化测试框架和脚本&#xff1b; 调试并维护脚本&#xff1b; 无人值守测试&#xff1b; 后期脚本维…

【数据结构】深入探讨二叉树的遍历和分治思想(一)

&#x1f6a9;纸上得来终觉浅&#xff0c; 绝知此事要躬行。 &#x1f31f;主页&#xff1a;June-Frost &#x1f680;专栏&#xff1a;数据结构 &#x1f525;该文章主要讲述二叉树的递归结构及分治算法的思想。 目录&#xff1a; &#x1f30d;前言&#xff1a;&#x1f30d;…

Sora 原理与技术实战笔记一

b 站视频合集 【AIX组队学习】Sora原理与技术实战&#xff1a;Sora技术路径详解 Sora 技术报告&#xff08;OpenAI&#xff09; huggingsd 文生图视频系列的一个开源项目 最强视频生成模型Sora相关技术解析 https://github.com/lichao-sun/SoraReview 惊艳效果&#xff1a; 长…

【Linux】screen

文章目录 一、screen二、功能三、使用3.1 安装3.2 常用参数3.3 状态3.4 使用3.4.1 终端列表3.4.2 新建screen3.4.3 detached3.4.4 回到终端3.4.5 清除终端 一、screen screen为多视窗管理程序。在服务器上搭建一些服务的时候&#xff0c;经常要用到screen命令。例如某些服务开…

云呐智能运维包含哪些内容?运维未来的发展方向是什么?

智能运维&#xff08;AIOps&#xff09;是一种使用人工智能应用程序来调节IT操作和维护的实践方式。它结合了大数据和机器学习技术&#xff0c;旨在自动化和改进IT操作和维护任务&#xff0c;如故障检测、因果分析和自动故障修复。以下是智能操作和维护的具体内容、挑战和解决方…

使用Node.js构建一个简单的聊天机器人

当谈到人工智能&#xff0c;我们往往会想到什么&#xff1f;是智能语音助手、自动回复机器人等。在前端开发领域中&#xff0c;我们也可以利用Node.js来构建一个简单而有趣的聊天机器人。本文将带你一步步实现一个基于Node.js的聊天机器人&#xff0c;并了解其工作原理。 首先…

文生图项目总结

文生图 功能点 页面进来获取背景图url和图片宽高&#xff08;根据比例和手机屏幕处理过的宽高&#xff09;渲染图片&#xff08;背景图最后生成图片模糊&#xff0c;换成img展示解决&#xff09;添加多个文字&#xff0c;编辑文字内容&#xff0c;拖拽改变文字位置&#xff0c…

上云还是下云,最大挑战是什么?| 对话章文嵩、毕玄、王小瑞

近半年来&#xff0c;公有云领域频频发生阿里云、滴滴等平台崩溃事件&#xff0c;与此同时&#xff0c;马斯克的“X 下云省钱”言论引起了广泛关注&#xff0c;一时间&#xff0c;“上云”和“下云”成为热议话题。在最近举办的 AutoMQ 云原生创新论坛上&#xff0c;AutoMQ 联合…

大数据可视化python01

import pandas as pd import matplotlib.pyplot as plt# 设置中文改写字体 plt.rcParams[font.sans-serif] [SimHei]# 读取数据 data pd.read_csv(C:/Users/wzf/Desktop/读取数据进行数据可视化练习/实训作业练习/瓜果类单位面积产量.csv ,encoding utf-8)#输出 print(data)…

springcloud alibaba组件简介

一、Nacos 服务注册中心/统一配置中心 1、介绍 Nacos是一个配置中心&#xff0c;也是一个服务注册与发现中心。 1.1、配置中心的好处&#xff1a; &#xff08;1&#xff09;配置数据脱敏 &#xff08;2&#xff09;防止出错&#xff0c;方便管理 &#xff08;3&#xff…

一本通 1403:素数对

在判断素数对的两个数是否都为素数时可以只判断数的一半 #include<bits/stdc.h> using namespace std; bool su(int a,int b){ for(int i2;i<sqrt(a);i){ if(a%i0){ return 0; } } for(int i2;i<sqrt(b);i){ if(…

AI大预言模型——ChatGPT在地学、GIS、气象、农业、生态、环境等应用

原文链接&#xff1a;AI大预言模型——ChatGPT在地学、GIS、气象、农业、生态、环境等应用 一开启大模型 1 开启大模型 1)大模型的发展历程与最新功能 2)大模型的强大功能与应用场景 3)国内外经典大模型&#xff08;ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Di…

Java底层自学大纲_中间件原理篇

中间件原理专题_自学大纲所属类别学习主题建议课时&#xff08;h&#xff09; A Web服务器Tomcat8原理分析001 Tomcat8底层架构模式2.5 A Web服务器Tomcat8原理分析002 Tomcat8底层源码深度分析2.5 A Web服务器Tomcat8原理分析003 站在微服务架构角度优化Tomcat82.5 B 分布…

SpringMVC基础概述

目录 MVC核心组件RequestMapping注解域对象共享数据视图RESTful请求与响应HttpMessageConverter请求响应 拦截器配置异常处理基于配置的异常处理基于注解的异常处理 配置类与注解配置MVC执行流程 Spring MVC是Spring Framework提供的Web组件&#xff0c;全称是Spring Web MVC&a…

ConcurrentHashMap的演进:从Java 8之前到Java 17的实现原理深度剖析

目录 一、引言二、Java 8之前的ConcurrentHashMap1、内部结构与初始化2、Segment类3、并发控制4、扩容与重哈希5、总结 三、Java 8中的ConcurrentHashMap1、数据结构2、并发控制2.1. CAS操作2.2. synchronized同步块 3、哈希计算与定位4、扩容与重哈希5、总结 四、Java 17中的C…

广汽埃安工厂:蔚来汽车的造车工厂有哪些?

具体来说&#xff0c;理想汽车目前在常州仅有一家汽车制造工厂。 一期项目于2017年12月竣工&#xff0c;2019年12月投产&#xff0c;年产能10万辆/年。 同时&#xff0c;正在规划二期工程。 产能将增至20万辆/年。 此外&#xff0c;理想还计划接管现代汽车在北京顺义的第一家工…