Qt实现TFTP Server和 TFTP Client(二)
3 实现
3.1 Core
Core模块包括下面4个类:
- TFTP
- BaseUdp
- TFtpClientFile
- TFtpServerFile
3.1.1 TFTP
TFTP类实现了TFTP协议。
3.1.1.1 TFTP定义
class TFtp
{
public:TFtp();enum Code {RRQ = 0x0001,//Read requestWRQ = 0x0002,//Write requestDATA = 0x0003,//Data requestACK = 0x0004,//AcknowledgementERROR = 0x0005 //Error};enum Mode { BINARY, ASCII, MAIL };enum Error {NotDefined = 0x0000,FileNotFound = 0x0001,AccessViolation = 0x0002,DiskFull = 0x0003,IllegalOperation = 0x0004,UnknownTransferID = 0x0005,FileExists = 0x0006,NoSuchUser = 0x0007,};enum Size {CODE_SIZE = 2,HEADER_SIZE = 4,BLOCK_SIZE = 512};enum Type { None, Read, Write };bool process(uint8_t const *data, uint32_t size);bool is_finished() const { return finished_; }bool is_error() const { return !error_msg_.empty(); }Error error() const { return error_; }std::string error_msg() const { return error_msg_; }
protected:virtual void on_read_req(std::string const& filename, Mode mode) {}virtual void on_write_req(std::string const& filename, Mode mode) {}virtual void on_data(uint16_t block_number, uint8_t const*data, uint32_t size) = 0;virtual void on_ack(uint16_t block_number) = 0;virtual void on_error(uint16_t error, std::string const& error_msg) = 0;virtual uint32_t write(uint8_t const *data, size_t size) = 0;void read_req(std::string const& filename, Mode mode);void write_req(std::string const& filename, Mode mode);void send(uint16_t block_number, size_t size);void resend();void ack(uint16_t block_number);void error(Error error, std::string const& error_msg);char *data() { return (char *)(data_ + HEADER_SIZE); }void set_error(Error error, std::string const& error_msg){error_ = error;error_msg_ = error_msg;}void finished() { finished_ = true; }size_t get_filesize(const char*filename);
private:uint16_t op_code(uint8_t const *data) { return static_cast<uint16_t>((data[0] << 8) | data[1]); }uint16_t block_num(uint8_t const *data) { return static_cast<uint16_t>((data[2] << 8) | data[3]); }uint16_t error_code(uint8_t const *data) { return static_cast<uint16_t>((data[2] << 8) | data[3]); }Mode getMode(std::string const& text);std::string getText(Mode mode);
private:uint8_t data_[HEADER_SIZE + BLOCK_SIZE];bool finished_ = false;TFtp::Error error_ = NotDefined;std::string error_msg_;size_t block_size_ = 0;
};
成员函数说明:
- process 解析数据包为TFtp::Code的请求包
- on_read_req 读请求虚函数,TFtpServerFile重载此函数
- on_write_req 写请求虚函数,TFtpServerFile重载此函数
- on_data 数据请求虚函数,TFtpServerFile/TFtpClientFile重载此函数
- on_ack 应答请求虚函数,TFtpServerFile/TFtpClientFile重载此函数
- on_error 出错处理虚函数,TFtpServerFile/TFtpClientFile重载此函数
- write 写数据虚函数,TFtpServerFile/TFtpClientFile重载此函数
- read_req 构造读请求数据包并发送
- write_req 构造写请求数据包并发送
- send 构造数据包请求并发送
- resend 重发数据包
- ack 构造应答请求数据包并发送
- error 构造出错数据包并发送
3.1.1.2 TFTP实现
- process/getMode
#define MIN_PACKET_LEN 4
bool TFtp::process(uint8_t const *data, uint32_t size)
{if(size < MIN_PACKET_LEN)return false;uint16_t code = op_code(data);if(code == RRQ || code == WRQ){uint8_t const*d = data + sizeof(uint16_t);uint8_t const*e = data + size;uint8_t const*s = d;while(s < e && *s)s++;std::string filename((char *)d, s - d);s++;d = s;while(s < e && *s)s++;std::string mode_text((char *)d, s - d);if(code == RRQ)on_read_req(filename, getMode(mode_text));elseon_write_req(filename, getMode(mode_text));return true;}else if(code == DATA){on_data(block_num(data), &data[HEADER_SIZE], size - HEADER_SIZE);return true;}else if(code == ACK){on_ack(block_num(data));return true;}else if(code == ERROR){uint8_t const* d = data + HEADER_SIZE;uint8_t const *e = data + size;uint8_t const *s = d;while(s < e && *s)s++;on_error(error_code(data), std::string((char *)d, s - d));return true;}return false;
}
TFtp::Mode TFtp::getMode(std::string const& text)
{if(text == "octet")return BINARY;else if(text == "netascii")return ASCII;elsereturn MAIL;
}
函数流程:
- 判断数据包长度小于最小长度4,解析失败返回
- 获取数据包的code。
- 根据code类型解析数据调用对应的接口函数。
- read_req/write_req/send/resend/ack/error
#define WITE_CODE(data, code) \data[0] = uint8_t(code >> 8); \data[1] = uint8_t(code >> 0);#define WITE_HEAD(data, code, value) \data[0] = uint8_t(code >> 8); \data[1] = uint8_t(code >> 0); \data[2] = uint8_t(value >> 8);\data[3] = uint8_t(value >> 0);void TFtp::read_req(std::string const& filename, Mode mode)
{std::string text = getText(mode);std::vector<uint8_t> data(CODE_SIZE + filename.size() + text.size() + 2, 0);WITE_CODE(data, RRQ)memcpy(&data[CODE_SIZE], filename.c_str(), filename.size());memcpy(&data[CODE_SIZE + filename.size() + 1], text.c_str(), text.size());write(&data[0], data.size());
}void TFtp::write_req(std::string const& filename, Mode mode)
{std::string text = getText(mode);std::vector<uint8_t> data(CODE_SIZE + filename.size() + text.size() + 2, 0);WITE_CODE(data, WRQ)memcpy(&data[CODE_SIZE], filename.c_str(), filename.size());memcpy(&data[CODE_SIZE + filename.size() + 1], text.c_str(), text.size());write(&data[0], data.size());
}void TFtp::send(uint16_t block_number, size_t size)
{WITE_HEAD(data_, DATA, block_number)block_size_ = size;write(data_, size + HEADER_SIZE);
}void TFtp::resend()
{write(data_, block_size_ + HEADER_SIZE);
}void TFtp::ack(uint16_t block_number)
{std::vector<uint8_t> data(HEADER_SIZE);WITE_HEAD(data, ACK, block_number)write(&data[0], data.size());
}void TFtp::error(Error error, std::string const& error_msg)
{std::vector<uint8_t> data(HEADER_SIZE + error_msg.size() + 1);error_ = error;error_msg_ = error_msg;finished();WITE_HEAD(data, ERROR, error)memcpy(&data[HEADER_SIZE], error_msg.c_str(), error_msg.size());data[data.size() - 1] = 0;write(&data[0], data.size());
}
函数说明:根据请求类型构造对应的请求包并发送。
3.1.2 BaseUdp
class BaseUdp
{
public:virtual ~BaseUdp(){}virtual uint32_t write(const char* data, size_t size) = 0;
};
类型说名:
- 定义udp的写接口,该接口需要TFtpServer和TFtpClient去实现。
3.1.3 TFtpClientFile
TFtpClientFile类实现客户端文件收发
3.1.3.1 TFtpClientFile定义
class TFtpClientFile : public TFtp
{
public:TFtpClientFile(BaseUdp *udp): udp_(udp), type_(None){}~TFtpClientFile();bool getFile(std::string const& local_filename,std::string const& remote_filename, Mode mode);bool putFile(std::string const& local_filename,std::string const& remote_filename, Mode mode);size_t filesize() const { return filesize_; }size_t file_bytes() const { return file_bytes_; }using Ptr = std::shared_ptr<TFtpClientFile>;
protected:void on_data(uint16_t block_number, uint8_t const* data, uint32_t size) override;void on_ack(uint16_t block_number) override;void on_error(uint16_t error, std::string const& error_msg) override;uint32_t write(uint8_t const *data, size_t size) override;
private:void send_data(uint16_t block_number);
private:BaseUdp* udp_;Type type_;std::ifstream read_file;std::ofstream write_file;uint16_t block_number_ = 0;uint32_t block_size_ = 0;size_t filesize_ = 0;size_t file_bytes_ = 0;
};
成员函数说明:
- getFile 下载文件
- putFile 上传文件
- on_data 实现数据请求
- on_ack 实现应答请求
- on_error 实现出错处理
- write 实现写功能
- send_data 从文件读取数据包并发送。
3.1.3.2 TFtpClientFile实现
- getFile
bool TFtpClientFile::getFile(std::string const& local_filename,std::string const& remote_filename,Mode mode)
{if(mode == TFtp::BINARY)write_file.open(local_filename.c_str(),std::ifstream::out | std::ifstream::binary);elsewrite_file.open(local_filename.c_str());if(!write_file.is_open())return false;read_req(remote_filename, mode);type_ = Write;return true;
}
函数流程:
-
以写方式打开本地文件
-
发送读文件请求
-
将类型设置为写
-
putFile
if(mode == TFtp::BINARY)read_file.open(local_filename.c_str(),std::ifstream::in | std::ifstream::binary);elseread_file.open(local_filename.c_str());if(!read_file.is_open())return false;filesize_ = get_filesize(local_filename.c_str());write_req(remote_filename, mode);type_ = Read;return true;
函数流程:
-
以读方式打开本地文件
-
发送写文件请求
-
将类型设置为读
-
on_data
void TFtpClientFile::on_data(uint16_t block_number, uint8_t const* data, uint32_t size)
{if(type_ != Write){error(IllegalOperation, "Illegal TFTP Operation in Data");return;}if(block_size_ == 0)block_size_ = size;write_file.write((char *)data, size);file_bytes_ += size;ack(block_number);if(size < block_size_){filesize_ = file_bytes_;finished();write_file.close();}
}
函数流程:
-
保存数据包
-
发送应答
-
处理最后一个包
-
下载结束
-
on_ack
void TFtpClientFile::on_ack(uint16_t block_number)
{if(type_ != Read){error(IllegalOperation, "Illegal TFTP Operation in ACK");return;}if(read_file.eof()){std::cout << "send data is finished" << std::endl;finished();return;}if(block_number_ != block_number)resend();else{block_number_++;send_data(block_number_);}
}
函数流程:
-
如果文件上传完毕,结束上传。
-
BlockNumber不同,则重传。
-
上传下一Block。
-
on_error
void TFtpClientFile::on_error(uint16_t error, std::string const& error_msg)
{set_error((Error)error, error_msg + std::string(" come from remote"));finished();
}
- send_data
void TFtpClientFile::send_data(uint16_t block_number)
{char* d = data();read_file.read(d, TFtp::BLOCK_SIZE);file_bytes_ += read_file.gcount();send(block_number, read_file.gcount());
}
- write
uint32_t TFtpClientFile::write(uint8_t const *data, size_t size)
{return udp_->write((const char*)data, size);
}
3.1.4 TFtpServerFile
TFtpServerFile类实现服务端文件收发
3.1.4.1 TFtpServerFile定义
class TFtpServerFile : public TFtp
{
public:TFtpServerFile(BaseUdp *udp, std::string const& path, std::string const& id): udp_(udp), type_(None), file_path_(path), transfer_id_(id), block_number_(0){}~TFtpServerFile();using Ptr = std::shared_ptr<TFtpServerFile>;std::string transfer_id() const { return transfer_id_; }Type type() const { return type_; }std::string filename() const { return filename_; }uint16_t block_number() const { return block_number_; }uint16_t block_numbers() const { return static_cast<uint16_t>((filesize_ + BLOCK_SIZE - 1) / BLOCK_SIZE); }size_t filesize() const { return filesize_; }size_t file_bytes() const { return file_bytes_; }
protected:void on_read_req(std::string const& filename, Mode mode) override;void on_write_req(std::string const& filename, Mode mode) override;void on_data(uint16_t block_number, uint8_t const* data, uint32_t size) override;void on_ack(uint16_t block_number) override;void on_error(uint16_t error, std::string const& error_msg) override;uint32_t write(uint8_t const *data, size_t size) override;
private:void send_data(uint16_t block_number);std::string full_fileaname(std::string const& filename) const {return file_path_ + filename;}TFtpServerFile(TFtpServerFile const&);TFtpServerFile(TFtpServerFile &&);TFtpServerFile operator == (TFtpServerFile const&);TFtpServerFile operator == (TFtpServerFile &&);
private:BaseUdp* udp_;Type type_;std::string filename_;std::string file_path_;std::string transfer_id_;std::ifstream read_file;std::ofstream write_file;uint16_t block_number_;uint32_t block_size_ = 0;size_t filesize_ = 0;size_t file_bytes_ = 0;
};
成员函数说明:
- transfer_id 返回唯一传输ID,用来管理多个TFtpServerFile实例。
- on_read_req 实现读请求。
- on_write_req 实现写请求。
- on_data 实现数据请求。
- on_ack 实现应答请求。
- on_error 实现出错处理。
- write 实现写功能。
- send_data 从文件读取数据包并发送。
3.1.4.2 TFtpServerFile实现
- on_read_req
void TFtpServerFile::on_read_req(std::string const& filename, Mode mode)//read
{if(type_ != None){error(IllegalOperation, "Illegal TFTP Operation in RRQ");return;}type_ = Read;filename_ = full_fileaname(filename);if(mode == TFtp::BINARY)read_file.open(filename_.c_str(),std::ifstream::in | std::ifstream::binary);elseread_file.open(filename_.c_str());if(!read_file.is_open())error(FileNotFound, std::string("File(") + filename + std::string(") Not Found"));else{block_number_ = 1;filesize_ = get_filesize(filename_.c_str());send_data(block_number_);}
}
函数流程:
-
以读方式打开文件
-
设置类型为读
-
发送第一个Block数据
-
on_write_req
void TFtpServerFile::on_write_req(std::string const& filename, Mode mode)//write
{if(type_ != None){error(IllegalOperation, "Illegal TFTP Operation in WRQ");return;}filename_ = full_fileaname(filename);if(get_filesize(filename_.c_str()) > 0){error(FileExists, "File Exists in WRQ");return;}type_ = Write;if(mode == TFtp::BINARY)write_file.open(filename_.c_str(),std::ifstream::out | std::ifstream::binary);elsewrite_file.open(filename_.c_str());if(!write_file.is_open())error(AccessViolation, "Access Violation");elseack(block_number_);//ack(0)
}
函数流程:
-
以写方式打开文件。
-
设置类型为写
-
请求第一块数据
-
on_data
void TFtpServerFile::on_data(uint16_t block_number, uint8_t const* data, uint32_t size) //write
{if(type_ != Write){error(IllegalOperation, "Illegal TFTP Operation in Data");return;}if(block_number != block_number_ + 1)ack(block_number_);else{if(block_size_ == 0)block_size_ = size;write_file.write((char *)data, size);file_bytes_ += size;ack(block_number);block_number_ = block_number;if(size < block_size_){filesize_ = file_bytes_;write_file.close();finished();}}
}
函数流程:
-
Block号不一致,则请求前一个块号。
-
保存数据包
-
保存最后数据包,
-
上传结束
-
on_ack
void TFtpServerFile::on_ack(uint16_t block_number) // read
{if(type_ != Read){error(IllegalOperation, "Illegal TFTP Operation in ACK");return;}if(read_file.eof()){finished();return;}if(block_number != block_number_)resend();else{block_number_++;send_data(block_number_);}
}
函数流程:
-
如果文件发送完毕,则结束
-
BlockNumber不一致,则重传
-
增加BlockNumber,发送Block数据
-
on_error
void TFtpServerFile::on_error(uint16_t error, std::string const& error_msg) //read/write
{set_error((Error)error, error_msg + std::string(" come from remote"));finished();
}
- write
uint32_t TFtpServerFile::write(uint8_t const *data, size_t size)
{return udp_->write((const char*)data, size);
}
- send_data
void TFtpServerFile::send_data(uint16_t block_number)
{char* d = data();read_file.read(d, TFtp::BLOCK_SIZE);file_bytes_ += read_file.gcount();send(block_number, read_file.gcount());
}
Qt实现TFTP Server和 TFTP Client(一) Qt实现TFTP Server和 TFTP Client(三)
相关文章:

Qt实现TFTP Server和 TFTP Client(二)
3 实现 3.1 Core Core模块包括下面4个类: TFTPBaseUdpTFtpClientFileTFtpServerFile 3.1.1 TFTP TFTP类实现了TFTP协议。 3.1.1.1 TFTP定义 class TFtp { public:TFtp();enum Code {RRQ 0x0001,//Read requestWRQ 0x0002,//Write requestDATA 0x0003…...

【b站李炎恢】Vue.js Element UI | 十天技能课堂 | 更新中... | 李炎恢
课程地址:【Vue.js Element UI | 十天技能课堂 | 更新中... | 李炎恢】 https://www.bilibili.com/video/BV1U54y127GB/?share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 备注:虽然标题声明还在更新中,但是看一些常用…...

AI大语言模型工程师学习路线
文章目录 运行LLMSLLM APIS开源的大语言模型Prompt engineering1. 明确目标2. 理解模型能力3. 使用示例4. 精确和具体的指令5. 考虑上下文6. 避免偏见和不准确的信息7. 测试和迭代8. 使用模板9. 考虑多语言能力10. 注意伦理和合规性结构化输出1. 使用明确的提示(Prompts)2. 采…...

基于树莓派实现 --- 智能家居
最效果展示 演示视频链接:基于树莓派实现的智能家居_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Tr421n7BM/?spm_id_from333.999.0.0 (PS:房屋模型的搭建是靠纸板箱和淘宝买的家居模型,户型参考了留学时短租的公寓~&a…...

基于Arduino IDE 野火ESP8266模块 一键配网 的开发
一、配网介绍 ESP8266 一键配网(也称为 SmartConfig 或 FastConfig)是一种允许用户通过智能手机上的应用程序快速配置 ESP8266 Wi-Fi 模块的方法,而无需手动输入 SSID 和密码。为了实现这一功能,则需要一个支持 SmartConfig 的智能…...

左手医生:医疗 AI 企业的云原生提效降本之路
相信这样的经历对很多人来说并不陌生:为了能到更好的医院治病,不惜路途遥远奔波到大城市;或者只是看个小病,也得排上半天长队。这些由于医疗资源分配不均导致的就医问题已是老生长谈。 云计算、人工智能、大数据等技术的发展和融…...

ceph集群部署
1. 每台服务器各增加2块硬盘(类型最好是相同的) 2. 将三台主机名设为node1.openlab.edu、node2.openlab.edu、node3.openlab.edu 3. 登录所有主机,配置 /etc/hosts 文件 192.168.136.55 ceph1.openlab.edu ceph1 192.168.136.56 ceph2.openlab.edu ceph2 192.168…...

C#WPF控件Label宽度绑定到父控件的宽度
如何将Label的宽度绑定到它所在Grid的宽度。跟随父控件的宽度的改变而改变。 <Window x:Class="WpfApp.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&q…...

HMI的学习
什么是HMI?了解HMI或人机界面的一些基础知识_哔哩哔哩_bilibili Human Machine Interface 人机界面 在工业中使用HMI来控制和监视设备 常见的HMI是ATM机 通过屏幕和按钮来完成取款或存款 工业中,操作员或维护人员可以从HMI操作和监视设备。 它们可能…...

工业无线网关在汽车制造企业的应用效果和价值-天拓四方
随着智能制造的快速发展,工业无线网关作为关键通信设备,在提升生产效率、优化生产流程、实现设备间的互联互通等方面发挥着越来越重要的作用。以下是一个关于工业无线网关在智能制造行业应用的具体案例,展示了其在实际生产中的应用效果和价值…...

校园app开发流程-uniapp开发-支持APP小程序H5-源码交付-跑腿-二手市场-交友论坛等功能,学校自由选择!
随着科技的不断发展,智慧校园系统和跑腿外卖小程序已经成为当今社会的热门话题。作为未来的重要趋势之一,科技在教育领域中的应用越来越广泛。本文将探讨智慧校园系统和跑腿外卖小程序的开发过程,并阐述如何利用科技“育”见未来 一、智慧校…...

Machine Learning机器学习之K近邻算法(K-Nearest Neighbors,KNN)
目录 前言 背景介绍: 思想: 原理: KNN算法关键问题 一、构建KNN算法 总结: 博主介绍:✌专注于前后端、机器学习、人工智能应用领域开发的优质创作者、秉着互联网精神开源贡献精神,答疑解惑、坚持优质作品共…...

四、在数据库里建库
一、查库 ##1)库:一个库就是一个excell文档,库里含有表,一个表就是一个excell的sheet. ##2)查看数据库实例中有哪些库 MariaDB [(none)]> show databases; -------------------- | Database | -------------------- | informat…...

蓝桥杯-网络安全比赛(2)基础学习-正则表达式匹配电话号码、HTTP网址、IP地址、密码校验
正则表达式(Regular Expression):定义:一种强大的文本处理工具,用于描述、匹配和查找字符串中的特定模式。应用:密码验证、文本搜索和替换、数据清洗等。特点:通过特定的元字符和规则来构建复杂…...

如何创建azure pipeline
Azure Pipelines是一种持续集成和持续交付(CI/CD)工具,可以帮助开发团队自动化构建、测试和部署应用程序。以下是创建Azure Pipeline的步骤: 登录到Azure DevOps(https://dev.azure.com/)。在Azure DevOps…...

缓存菜品、套餐、购物车相关功能
一、缓存菜品 通过缓存的方式提高查询性能 1.1问题说明 大量的用户访问导致数据库访问压力增大,造成系统响应慢,用户体验差 1.2 实现思路 优先查询缓存,如果缓存没有再去查询数据库,然后载入缓存 将菜品集合序列化后缓存入red…...

微信小程序的页面交互1
一、page()函数 每个页面的s代码全部写入对应的js文件的page()函数里面。点击编译,就可以显示js代码的运行效果。注意,每个页面的page()函数是唯一的。 page(ÿ…...

win10 docker zookeeper和kafka搭建
好久没用参与大数据之类的开发了,近日接触到一个项目中使用到kafka,因此要在本地搭建一个简易的kafka服务。时间比较紧急,之前有使用docker的经验,因此本次就使用docker来完成搭建。在搭建过程中出现的一些问题,及时记…...

【Redis】快速入门 数据类型 常用指令 在Java中操作Redis
文章目录 一、简介二、特点三、下载与安装四、使用4.1 服务器启动4.2 客户端连接命令4.3 修改Redis配置文件4.4 客户端图形化界面 五、数据类型5.1 五种常用数据类型介绍5.2 各种数据类型特点 六、常用命令6.1 字符串操作命令6.2 哈希操作命令6.3 列表操作命令6.4 集合操作命令…...

【tingsboard开源平台】下载数据库,IDEA编译,项目登录
一, PostgreSQL 下载 需要看官网的:点此下载直达地址:点此进行相关学习:PostgreSQL 菜鸟教程 二,PostgreSQL 安装 点击安装包进行安装 出现乱码错误: There has been an error. Error running C:\Wind…...

Web3:探索区块链与物联网的融合
引言 随着科技的不断发展,区块链技术和物联网技术都成为了近年来备受瞩目的前沿技术。而当这两者结合在一起,将产生怎样的化学反应呢?本文将深入探讨Web3时代中区块链与物联网的融合,探索其意义、应用场景以及未来发展趋势。 1. …...

[BT]BUUCTF刷题第9天(3.27)
第9天(共2题) [护网杯 2018]easy_tornado 打开网站就是三个txt文件 /flag.txt flag in /fllllllllllllag/welcome.txt render/hints.txt md5(cookie_secretmd5(filename))当点进flag.txt时,url变为 http://b9e52e06-e591-46ad-953e-7e8c5f…...

html页面使用@for(){},@if(){},利用jquery 获取当前class在列表中的下标
基于以前的项目进行修改优化,前端代码根据List元素在html里进行遍历显示 原先的代码: 其中,noticeGuide.Id是标识noticeGuide的唯一值,但是不是从0开始的【是数据库自增字段】 但是在页面初始化加载的时候,我们只想…...

pulsar: 批量接收消息
接收消息时,和kafka类似,如果topic有多个分区,则只能保证分区内数据的接收有序,不能保证全局有序。 一、发送消息 package cn.edu.tju.test1;import org.apache.pulsar.client.api.*;public class BatchProducer01 {private sta…...

LNMP架构之mysql数据库实战
mysql安装 到官网www.mysql.com下载源码版本 实验室使用5.7.40版本 tar xf mysql-boost-5.7.40.tar.gz #解压 cd mysql-boost-5.7.40/ yum install -y cmake gcc-c bison #安装依赖性 cmake -DCMAKE_INSTALL_PREFIX/usr/local/mysql -DMYSQL_DATADIR/data/mysql -DMYSQL_…...

aws使用记录
数据传输(S3) 安装命令行 安装awscli: https://docs.aws.amazon.com/zh_cn/cli/latest/userguide/getting-started-install.html#getting-started-install-instructions 直到 aws configure list 可以运行 身份验证: 运行: aws config…...

区块链食品溯源案例实现(二)
引言 随着前端界面的完成,我们接下来需要编写后端代码来与区块链网络进行交互。后端将负责处理前端发送的请求,调用智能合约的方法获取食品溯源信息,并将结果返回给前端。 通过前后端的整合,我们可以构建一个食品溯源系统…...

RabbitMQ(简单模式)
2种远程服务调用 1openFeign: 优点:能拿到被调用的微服务返回的数据,系统系耦度高,系统稳定。 缺点:同步调用,如果有很多服务需要被调用,耗时长。 MQ,消息队列,RabbitMQ是消息we…...

ES集群部署的注意事项
文章目录 引言I ES集群部署前期工作II 部署ES2.1 配置安全组2.2 创建ES用户和组2.3 下载安装ES2.4 修改内存相关配置III es集群添加用户安全认证功能3.1 生成 elastic-certificates.p123.2 创建 Elasticsearch 集群密码3.2 设置kibana的 elasticsearch帐号角色和密码3.3 logsta…...

Etcd 基本入门
1:什么是 Etcd ? Etcd 是 CoreOS 团队于2013年6月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库。etcd内部采用raft协议作为一致性算法,Etcd基于 Go 语言实现。 名字由来,它源于两个方面,…...