libevent高并发网络编程 - 05_libevent实现http客户端

文章目录

    • 1 http客户端相关的API
      • evhttp_uri_parse()
      • evhttp_uri_get_scheme()
      • evhttp_uri_get_port()
      • evhttp_uri_get_host()
      • evhttp_uri_get_path()
      • evhttp_uri_get_query()
      • evhttp_connection_base_bufferevent_new()
      • evhttp_request_new()
      • evhttp_make_request()
      • evhttp_request_get_response_code()
      • evhttp_request_get_response_code_line()
      • evbuffer_add_printf()
    • 2 编写http客户端的流程
      • 对url解析端口、主机名部分、路径部分等
      • 完成http客户端的请求
      • 响应回调函数
    • 3 完成的http客户端程序

1 http客户端相关的API

evhttp_uri_parse() 用于解析 URI 字符串并创建一个 evhttp_uri 结构体表示该 URI

evhttp_uri_parse()

struct evhttp_uri *
			evhttp_uri_parse(const char *source_uri)
    
返回一个指向 evhttp_uri 结构体的指针,该结构体包含了 URI 的各个组成部分(包括协议、主机名、端口号、路径、查询参数和片段标识符等)
    
    
struct evhttp_uri {
	unsigned flags;
	char *scheme; 	/* scheme; e.g http, ftp etc */
	char *userinfo; /* userinfo (typically username:pass), or NULL */
	char *host; 	/* hostname, IP address, or NULL */
	int port; 		/* port, or zero */
#ifndef _WIN32
	char *unixsocket; /* unix domain socket or NULL */
#endif
	char *path; 	/* path, or "". */
	char *query; 	/* query, or NULL */
	char *fragment; /* fragment or NULL */
};

evhttp_uri_get_scheme()

evhttp_uri_get_scheme() 用于获取 URI 的协议部分(即 :// 前面的部分)

const char *
evhttp_uri_get_scheme(const struct evhttp_uri *uri)
{
	return uri->scheme;
}

函数返回一个字符串指针,指向 URI 的协议部分。如果 URI 中没有明确指定协议,则返回空指针。
    
http://ffmpeg.club/index.html?id=1 =》 http

evhttp_uri_get_port()

evhttp_uri_get_port() 用于获取 URI 的端口号

int
evhttp_uri_get_port(const struct evhttp_uri *uri)
{
	return uri->port;
}

函数返回一个整数,表示 URI 的端口号。如果 URI 中没有明确指定端口号,则返回默认值(HTTP 协议默认端口为 80,HTTPS 协议默认端口为 443)
    
http://ffmpeg.club/index.html?id=1 =》 80

evhttp_uri_get_host()

evhttp_uri_get_host() 用于获取 URI 的主机名部分。

const char *
evhttp_uri_get_host(const struct evhttp_uri *uri)
{
	return uri->host;
}

函数返回一个字符串指针,指向 URI 的主机名部分。如果 URI 中没有明确指定主机名,则返回空指针。
    
http://ffmpeg.club/index.html?id=1 =》 ffmpeg.club

evhttp_uri_get_path()

evhttp_uri_get_path() 用于获取 URI 的路径部分。

const char *
evhttp_uri_get_path(const struct evhttp_uri *uri)
{
	return uri->path;
}

函数返回一个字符串指针,指向 URI 的路径部分。如果 URI 中没有明确指定路径,则返回空字符串。
    
http://ffmpeg.club/index.html?id=1 =》 /index.html

evhttp_uri_get_query()

evhttp_uri_get_query() 用于获取 URI 的查询部分,获取路径后面的参数。

const char *
evhttp_uri_get_query(const struct evhttp_uri *uri)
{
	return uri->query;
}

http://ffmpeg.club/index.html?id=1 =》 id=1

evhttp_connection_base_bufferevent_new()

evhttp_connection_base_bufferevent_new() 用于创建一个 evhttp_connection 对象,表示基于网络连接的 HTTP 客户端

该函数使用一个 bufferevent 对象来处理底层的网络 I/O,并使用指定的 DNS 解析器解析主机名。如果 dnsbase 参数为 NULL,则表示使用默认的全局 DNS 解析器。

struct evhttp_connection *
	evhttp_connection_base_bufferevent_new(struct event_base *base, 
                                           struct evdns_base *dnsbase, 
                                           struct bufferevent* bev,
                                           const char *address, 
                                           unsigned short port)
参数:
    base:事件处理器对象,用于安排事件处理和超时。
    dnsbase:指定的 DNS 解析器解析主机名。如果dnsbase 参数为 NULL,则表示使用默认的全局 DNS 解析器。
    bev: bufferevent对象
    address:服务器的 IP 地址或主机名。
    port:服务器的端口号。

evhttp_request_new()

evhttp_request_new() 用于创建一个 evhttp_request 对象,表示 HTTP 请求

struct evhttp_request *
			evhttp_request_new(void (*cb)(struct evhttp_request *, void *), 
                               void *arg)
该函数需要以下参数:
    cb:回调函数,当请求处理完成后调用。可以为 NULL,表示不需要回调函数。
    arg:传递给回调函数的额外参数。
    
    

需要注意的是,在使用完 evhttp_request 对象后,必须手动释放其所占用的内存空间:

evhttp_request_free(req);

evhttp_make_request()

evhttp_make_request() 用于向指定的 evhttp_connection 对象发起 HTTP 请求。

int
evhttp_make_request(struct evhttp_connection *evcon,
    				struct evhttp_request *req,
    				enum evhttp_cmd_type type, 
                    const char *uri)
    
该函数需要以下参数:
    evcon:表示要使用的 evhttp_connection 对象。
    req:表示要发送的 HTTP 请求。
    type:表示 HTTP 方法类型,可以是 GET、POST、DELETE 等等。
    uri:表示请求的 URI。

evhttp_request_get_response_code()

获取一个HTTP请求的响应状态码

int
evhttp_request_get_response_code(const struct evhttp_request *req)
{
	return req->response_code;
}

evhttp_request_get_response_code_line()

返回参数req所指向的结构体中的response_code_line成员变量的值,即HTTP响应状态码行,例如“HTTP/1.1 200 OK”。因此,调用该函数可以获取一个HTTP请求的完整响应状态行

const char *
evhttp_request_get_response_code_line(const struct evhttp_request *req)
{
	return req->response_code_line;
}

evbuffer_add_printf()

int
	evbuffer_add_printf(struct evbuffer *buf, 
                        const char *fmt, ...)

2 编写http客户端的流程

对url解析端口、主机名部分、路径部分等

发送http请求前,需要对目标的URL进行解析。

例如:http://ffmpeg.club/index.html?id=1
协议部分:http
端口号:80
主机名部分:ffmpeg.club
路径部分:/index.html
参数:id=1
string http_url = "http://ffmpeg.club/index.html?id=1";
//http_url = "http://ffmpeg.club/101.jpg";

// 分析url地址
// 解析 URI 字符串并创建一个 evhttp_uri 结构体表示该 URI
evhttp_uri *uri = evhttp_uri_parse(http_url.c_str());

// http https 获取 URI 的协议部分(即 :// 前面的部分)
const char *scheme = evhttp_uri_get_scheme(uri);
if (!scheme)
{
    cerr << "scheme is null" << endl;
    return -1;
}
cout << "scheme is " << scheme << endl;

//获取 URI 的端口号
int port = evhttp_uri_get_port(uri);
if (port < 0)
{
    if (strcmp(scheme, "http") == 0)
        port = 80;
}
cout << "port is " << port << endl;

//获取 URI 的主机名部分 host ffmpeg.club 
const char *host = evhttp_uri_get_host(uri);
if (!host)
{
    cerr << "host is null" << endl;
    return -1;
}
cout << "host is " << host << endl;

//获取 URI 的路径部分
const char *path = evhttp_uri_get_path(uri);
if (!path || strlen(path) == 0)
{
    path = "/";
}
if (path)
    cout << "path is " << path << endl;

//获取 URI 的查询部分,获取路径后面的参数
//?id=1  后面的内容 id=1
const char *query = evhttp_uri_get_query(uri);
if (query)
    cout << "query is " << query << endl;
else
    cout << "query is NULL" << endl;
输出结果:
    event_base_new success!
    scheme is http
    port is 80
    host is ffmpeg.club
    path is /index.html
    query is id=1

完成http客户端的请求

需要先创建一个 evhttp_connection 对象,evhttp_request_new并指定响应回调函数,配置请求头部和请求数据,最后通过evhttp_make_request指定请求类型和请求uri发送http请求。

// bufferevent  连接http服务器
bufferevent *bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);

//创建一个 evhttp_connection 对象,表示基于网络连接的 HTTP 客户端
evhttp_connection *evcon = evhttp_connection_base_bufferevent_new(base,
                                                                  NULL, bev, host, port);

//http client  请求 回调函数设置
evhttp_request *req = evhttp_request_new(http_client_cb, base);

// 设置请求的head 消息报头 信息
evkeyvalq *output_headers = evhttp_request_get_output_headers(req);
evhttp_add_header(output_headers, "Host", host);

//向指定的 evhttp_connection 对象发起 HTTP 请求
evhttp_make_request(evcon, req, EVHTTP_REQ_GET, path);

响应回调函数

服务器响应请求后,客户端会调用evhttp_request_new的回调函数,在请求回调函数中处理返回的数据。

cout << "http_client_cb" << endl;
event_base *base = (event_base *)ctx;
//服务端响应错误
if (req == NULL)
{
    int errcode = EVUTIL_SOCKET_ERROR();
    cout << "socket error:" << evutil_socket_error_to_string(errcode) << endl;
    return;
}

//获取path 
const char *path = evhttp_request_get_uri(req);
cout << "request path is " << path << endl;
string filepath = ".";
filepath += path;
cout << "filepath is " << filepath << endl;

//如果路径中有目录,需要分析出目录,并创建
FILE *fp = fopen(filepath.c_str(), "wb");
if (!fp)
{
    cout << "open file " << filepath<<" failed!" << endl;
}

//获取一个HTTP请求的响应状态码 200 404
cout << "Response :" << evhttp_request_get_response_code(req); 
//HTTP响应状态码行,例如“HTTP/1.1 200 OK”
cout <<" "<< evhttp_request_get_response_code_line(req) << endl;

char buf[1024] = {0};
evbuffer *input = evhttp_request_get_input_buffer(req);
for (;;)
{
    int len = evbuffer_remove(input,buf,sizeof(buf)-1);
    if (len <= 0)break;
    buf[len] = 0;
    if (!fp)
        continue;
    fwrite(buf, 1, len, fp);
    //cout << buf << flush;
}
if (fp)
    fclose(fp);

//退出循环
event_base_loopbreak(base);
输出结果:
    http_client_cb
    request path is /index.html
    filepath is ./index.html
    Response :200 

3 完成的http客户端程序

实现http客户端的GET、POST请求编写,请求服务器的文件并保存。

#include <event2/event.h>
#include <event2/listener.h>
#include <event2/http.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <string.h>
#include <string>
#ifndef _WIN32
#include <signal.h>
#endif
#include <iostream>
using namespace std;

/*响应回调函数*/
void http_client_cb(struct evhttp_request *req, void *ctx)
{
	cout << "http_client_cb" << endl;
	event_base *base = (event_base *)ctx;
	//服务端响应错误
	if (req == NULL)
	{
		int errcode = EVUTIL_SOCKET_ERROR();
		cout << "socket error:" << evutil_socket_error_to_string(errcode) << endl;
		return;
	}

	//获取path 
	const char *path = evhttp_request_get_uri(req);
	cout << "request path is " << path << endl;
	string filepath = ".";
	filepath += path;
	cout << "filepath is " << filepath << endl;
	
	//如果路径中有目录,需要分析出目录,并创建
	FILE *fp = fopen(filepath.c_str(), "wb");
	if (!fp)
	{
		cout << "open file " << filepath<<" failed!" << endl;
	}

	//获取一个HTTP请求的响应状态码 200 404
	cout << "Response :" << evhttp_request_get_response_code(req); 
	//HTTP响应状态码行,例如“HTTP/1.1 200 OK”
	cout <<" "<< evhttp_request_get_response_code_line(req) << endl;

	char buf[1024] = {0};
	evbuffer *input = evhttp_request_get_input_buffer(req);
	for (;;)
	{
		int len = evbuffer_remove(input,buf,sizeof(buf)-1);
		if (len <= 0)break;
		buf[len] = 0;
		if (!fp)
			continue;
		fwrite(buf, 1, len, fp);
		//cout << buf << flush;
	}
	if (fp)
		fclose(fp);

	//退出循环
	event_base_loopbreak(base);
}

/*发送GET请求*/
int TestGetHttp()
{
	//创建libevent的上下文
	event_base * base = event_base_new();
	if (base)
	{
		cout << "event_base_new success!" << endl;
	}

	//   生成请求信息 GET
	string http_url = "http://ffmpeg.club/index.html?id=1";
	//http_url = "http://ffmpeg.club/101.jpg";
	http_url = "http://127.0.0.1:8080/index.html";

	// 分析url地址
	// 解析 URI 字符串并创建一个 evhttp_uri 结构体表示该 URI
	evhttp_uri *uri = evhttp_uri_parse(http_url.c_str());

	// http https 获取 URI 的协议部分(即 :// 前面的部分)
	const char *scheme = evhttp_uri_get_scheme(uri);
	if (!scheme)
	{
		cerr << "scheme is null" << endl;
		return -1;
	}
	cout << "scheme is " << scheme << endl;

	//获取 URI 的端口号
	int port = evhttp_uri_get_port(uri);
	if (port < 0)
	{
		if (strcmp(scheme, "http") == 0)
			port = 80;
	}
	cout << "port is " << port << endl;

	//获取 URI 的主机名部分 host ffmpeg.club 
	const char *host = evhttp_uri_get_host(uri);
	if (!host)
	{
		cerr << "host is null" << endl;
		return -1;
	}
	cout << "host is " << host << endl;

	//获取 URI 的路径部分
	const char *path = evhttp_uri_get_path(uri);
	if (!path || strlen(path) == 0)
	{
		path = "/";
	}
	if (path)
		cout << "path is " << path << endl;

	//获取 URI 的查询部分,获取路径后面的参数
	//?id=1  后面的内容 id=1
	const char *query = evhttp_uri_get_query(uri);
	if (query)
		cout << "query is " << query << endl;
	else
		cout << "query is NULL" << endl;

	// bufferevent  连接http服务器
	bufferevent *bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);

	//创建一个 `evhttp_connection` 对象,表示基于网络连接的 HTTP 客户端
	evhttp_connection *evcon = evhttp_connection_base_bufferevent_new(base,
		NULL, bev, host, port);

	//http client  请求 回调函数设置
	evhttp_request *req = evhttp_request_new(http_client_cb, base);

	// 设置请求的head 消息报头 信息
	evkeyvalq *output_headers = evhttp_request_get_output_headers(req);
	evhttp_add_header(output_headers, "Host", host);

	//向指定的 evhttp_connection 对象发起 HTTP 请求
	evhttp_make_request(evcon, req, EVHTTP_REQ_GET, path);
	

	//事件分发处理
	if (base)
		event_base_dispatch(base);
	if (uri)evhttp_uri_free(uri);
	if (evcon)evhttp_connection_free(evcon);
	if (base)
		event_base_free(base);
}

int TestPostHttp()
{
	//创建libevent的上下文
	event_base * base = event_base_new();
	if (base)
	{
		cout << "event_base_new success!" << endl;
	}

	//   生成请求信息 GET
	string http_url = "http://127.0.0.1:8080/index.html";

	// 分析url地址
	// 解析 URI 字符串并创建一个 evhttp_uri 结构体表示该 URI
	evhttp_uri *uri = evhttp_uri_parse(http_url.c_str());

	// http https 获取 URI 的协议部分(即 :// 前面的部分)
	const char *scheme = evhttp_uri_get_scheme(uri);
	if (!scheme)
	{
		cerr << "scheme is null" << endl;
		return -1;
	}
	cout << "scheme is " << scheme << endl;

	//获取 URI 的端口号
	int port = evhttp_uri_get_port(uri);
	if (port < 0)
	{
		if (strcmp(scheme, "http") == 0)
			port = 80;
	}
	cout << "port is " << port << endl;

	//获取 URI 的主机名部分 host ffmpeg.club 
	const char *host = evhttp_uri_get_host(uri);
	if (!host)
	{
		cerr << "host is null" << endl;
		return -1;
	}
	cout << "host is " << host << endl;

	//获取 URI 的路径部分
	const char *path = evhttp_uri_get_path(uri);
	if (!path || strlen(path) == 0)
	{
		path = "/";
	}
	if (path)
		cout << "path is " << path << endl;

	//获取 URI 的查询部分,获取路径后面的参数
	//?id=1  后面的内容 id=1
	const char *query = evhttp_uri_get_query(uri);
	if (query)
		cout << "query is " << query << endl;
	else
		cout << "query is NULL" << endl;

	// bufferevent  连接http服务器
	bufferevent *bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);

	//创建一个 `evhttp_connection` 对象,表示基于网络连接的 HTTP 客户端
	evhttp_connection *evcon = evhttp_connection_base_bufferevent_new(base,
		NULL, bev, host, port);

	//http client  请求 回调函数设置
	evhttp_request *req = evhttp_request_new(http_client_cb, base);

	// 设置请求的head 消息报头 信息
	evkeyvalq *output_headers = evhttp_request_get_output_headers(req);
	evhttp_add_header(output_headers, "Host", host);

	//发送post数据
	evbuffer *output = evhttp_request_get_output_buffer(req);
	evbuffer_add_printf(output, "xcj=%d&b=%d", 1, 2);

	//向指定的 evhttp_connection 对象发起 HTTP 请求
	evhttp_make_request(evcon, req, EVHTTP_REQ_POST, path);
	

	//事件分发处理
	if (base)
		event_base_dispatch(base);
	if (uri)evhttp_uri_free(uri);
	if (evcon)evhttp_connection_free(evcon);
	if (base)
		event_base_free(base);
}

int main()
{
#ifdef _WIN32 
	//初始化socket库
	WSADATA wsa;
	WSAStartup(MAKEWORD(2,2),&wsa);
#else
	//忽略管道信号,发送数据给已关闭的socket
	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
		return 1;
#endif
	std::cout << "test http client!\n";
	TestGetHttp();	//发送GET请求
	TestPostHttp();	//发送POST请求
    
	
#ifdef _WIN32
	WSACleanup();
#endif
	return 0;
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

图像动态裁剪

1. 背景 以两级级联模型为例&#xff0c;第一级目标检测模型用于检测人员&#xff0c;第二级目标检测模型用于检测手机、对讲机等。然后实际数据采集过程中&#xff0c;手机、对讲机这些设备并不在人员的一级检测框内&#xff0c;使得二级模型训练的样本较少。 二级目标检测模…

即拼七人拼团系统开发模式,为什么这么火?

即拼七人拼团模式主要是结合了拼团模式的奖励机制和二二复制系统的排位玩法&#xff0c;将产品销售中的利润最大化让利于拼团的用户&#xff0c;刺激用户主动分享推广&#xff0c;以解决平台引流和用户活跃度的问题。 具体来说&#xff0c;即拼七人拼团模式就是用户进入平台购买…

ArrayList 和 LinkedList 之间应该怎么选择?

Joshua Bloch&#xff1a;我写了 LinkedList&#xff0c;但我自己都不用&#xff01; 对&#xff0c;Joshua Bloch 就是 LinkedList 的作者&#xff01; 如果你真信了作者的话&#xff0c;那就真的大错特错了&#xff0c;LinkedList 虽然用的没有 ArrayList 多&#xff0c;但使…

【致敬未来的攻城狮计划】— 连续打卡第二十七天:瑞萨RA RA2E1 的 BTN触摸按键

文章目录 由于一些特殊原因&#xff1a; 系列文章链接&#xff1a;&#xff08;其他系列文章&#xff0c;请点击链接&#xff0c;可以跳转到其他系列文章&#xff09;或者参考我的专栏“ 瑞萨MCU ”&#xff0c;里面是 瑞萨RA2E1 系列文章。 24.RA2E1的 DMAC——数据传输 25.R…

自学黑客(网络安全),一般人我劝你还是算了吧

一、自学网络安全学习的误区和陷阱 1.不要试图先成为一名程序员&#xff08;以编程为基础的学习&#xff09;再开始学习 我在之前的回答中&#xff0c;我都一再强调不要以编程为基础再开始学习网络安全&#xff0c;一般来说&#xff0c;学习编程不但学习周期长&#xff0c;而…

漏洞分析丨CVE-2012-1873

一、漏洞简述 cve-2012-1873同样是一个著名的堆溢出漏洞&#xff0c;他是IE6-8中MSHTL.dll中的CTableLayout::CalculateMinMax函数里&#xff0c;程序在执行时会以HTML代码中的元素span属性作为循环控制次数向堆中写入数据。第一次会优先根据span申请堆空间&#xff0c;当我们…

数据库事务

目录 一.事务 1.为什么要存在事务 2.什么是事务 3.事务的特性(ACID) 4.MySQL中事务的使用 二.事务的隔离级别 1.什么是隔离级别 2.隔离级别的分类 3.不同隔离级别的现象 4.MySQL中设置隔离级别 5. 四种隔离级别和锁 1.READ-UNCOMMITED 2.READ-COMMITED 3.REPEATAB…

前端实现可拖拽课程表【纯HTML、CSS、JS】

前言 hello&#xff0c;今天实现点小动画&#xff0c;帮助学习理解Web api的拖拽效果&#xff0c;这里实现的是可拖拽的课程表&#xff01;# 效果图 附&#xff1a;作者没钱去除水印&#xff0c;就这样看一下简单的看一下效果吧&#xff01; 实现前言知识 这里我使用事件委…

区间合并(算法)

目录 题目代码实现注意点 题目 给定 n n n 个区间 [ l i , r i ] [l_i, r_i] [li​,ri​]&#xff0c;要求合并所有有交集的区间。 注意如果在端点处相交&#xff0c;也算有交集。 输出合并完成后的区间个数。 例如&#xff1a; [ 1 , 3 ] [1,3] [1,3] 和 [ 2 , 6 ] [2,…

Maven POM和Maven构建配置文件操作笔记

目录 我到现在还是没有太搞懂Maven的作用&#xff0c;我只是有一个模糊的概念就是它可以添加很多的依赖&#xff0c;这样会使项目搭建起来更加方便&#xff0c;你可以谈谈你的看法吗&#xff1f; Maven POM 父&#xff08;Super&#xff09;POM POM 标签大全详解 Maven 构建…

DSP:数字信号处理的原理及应用

什么是DSP&#xff1f;DSP一般有两种解释&#xff1a; 1、Digital Signal Processing&#xff0c;数字信号处理技术&#xff0c;简称DSP。是一门涉及许多学科而又广泛应用于许多领域的新兴学科。数字信号处理是围绕着数字信号处理的理论、实现和应用等几个方面发展起来的。数字…

如何用u盘重装系统win7

​如今的U盘重装win7系统是比较常见的重装win7系统的方法&#xff0c;适用性比较高&#xff0c;操作也十分的简单。有的小伙伴想给自己的电脑重装win7&#xff0c;那么我们用u盘重装系统怎么安装win7?现在小编就来教大家如何用u盘重装系统教程。 工具/原料&#xff1a; 系统…

git commit 设置 eslint + pretter 格式化校验

系统版本 node 版本: v14.17.5 npm 版本: 6.14.14 vue-cli 版本: vue/cli 4.5.19 目录 系统版本 1. 新建一个 vue2.X 空项目 2. 安装插件 eslint ,并初始化 eslint 配置,根目录生成 .eslintrc 配置文件 3. 测试 eslint 配置 4. 安装 husky、lint-staged 5. 在package.j…

使用svg在元素直接绘制连线箭头

注意&#xff1a;svg的图形绘制的点位置坐标是基于画布的位置坐标&#xff0c;相当于从左上角的点为起点。 先来个简单示例&#xff1a; 在点与点之间绘制连线箭头 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8">…

ChatGPT学习-如何向ChatGPT提问

​ 最近在学习chatGPT,怎么样的提问是一个好的提问。通过网上找资料肯定不是最好的方法&#xff0c;我想起一句话&#xff0c;“不识庐山真面目&#xff0c;只缘身在此山中”。最好的老师就是chatGPT&#xff01; 下面先展示下提问成果&#xff0c;我通过xmind生成了思维导图 一…

科思转债上市价格预测

科思转债 基本信息 转债名称&#xff1a;科思转债&#xff0c;评级&#xff1a;AA-&#xff0c;发行规模&#xff1a;7.249178亿元。 正股名称&#xff1a;科思股份&#xff0c;今日收盘价&#xff1a;67.1元&#xff0c;转股价格&#xff1a;53.03元。 当前转股价值 转债面值…

电脑断电文件丢失如何找回?给你支几招!

电脑断电文件丢失如何找回&#xff1f;我好不容易熬夜加班做的活动方案&#xff0c;正当将U盘文件转移到笔记本电脑的时候&#xff0c;没有注意笔记本的电量&#xff0c;在转移数据的过程中突然断电了。我的电脑一下子就“熄”了&#xff0c;方案都没来得及保存。这真是一个悲剧…

MySQL主从复制与读写分离

目录 一、mysql主从复制原理1.1 mysql的复制类型1.2 mysql主从复制的工作原理 二、mysql读写分离原理2.1 读写分离的意义2.2 常见的两种mysql读写分离2.2.1.基于程序代码内部实现2.2.2.基于中间代理层实现2.2.3 amoeba 2.3 mysql读写分离原理 三、mysql数据库四种同步方式3.1 异…

MySQL视图详解

我写本文主要目的&#xff0c;是在网上看见了 所以&#xff0c;文本主要探讨的问题如下&#xff0c;验证结果在最后面 一、修改视图&#xff0c;基表会跟着改吗&#xff1f;答案&#xff1a;会改变 二、修改基表&#xff0c;视图会变化吗&#xff1f;答案&#xff1a;会改变 …

Nevron Open Vision for .NET 2022.3 Crack

Nevron Open Vision for .NET 适用于 Blazor、WPF、WinForms 和 Xamarin.Mac 的领先用户界面组件 Nevron Open Vision for .NET 是一套高级 UI 组件&#xff0c;可帮助您从单个代码库开发功能丰富的 Web &#xff08;Blazor WebAssembly&#xff09; 和桌面 &#xff08;WinFor…