APP下载

Facebook最新Libra币开发指南---界面服务器开发1

消息来源:baojiabao.com 作者: 发布时间:2024-05-29

报价宝综合消息Facebook最新Libra币开发指南---界面服务器开发1

在Libra Core中,官方提供了一个命令列工具,可以实现建立账户、挖矿和转账等基本操作,但是没有提供Restful界面,使我们想要开发的应用系统,将区块链逻辑移植到Libra Testnet上去。在本篇博文中,我们将利用Rust语言,将官方的命令列界面,改造成RESTful界面。由于我们只是临时改造,相信官方的RESTful界面很快就会出现,因此我们在这里仅使用最简实现,实现一个单执行绪的Web服务器来完成这一工作。

最简Web服务器

我们需要一个最简单的Web服务器,来接收客户端的请求,然后呼叫系统功能完成Libra Core中相关的区块链操作操作。我们先开发一个独立的应用,实现最基本的Web服务器功能,然后再将其整合到Libra Core的命令列工具中。

我们首先通过如下命令建立一个新工程:

cargo new libra_server --bin

我们建立一个名称为libra_server的工程,其为可执行档案形式。上面的命令会在当前目录下建立libra_server目录,并建立libra_server/src/main.rs档案,这个档案就是整个专案的主程式档案。

下面我们建立一个Hello World的Web服务器:

use std::io::prelude::*;

use std::net::TcpStream;

use std::net::TcpListener;

fn main() {

start_server();

}

fn start_server() {

println!("Libra Server v0.0.2 Starting up ...");

let listener = TcpListener::bind("127.0.0.1:7878").unwrap();

for stream in listener.incoming() {

let stream = stream.unwrap();

handle_connection(stream);

}

}

fn handle_connection(mut stream: TcpStream) {

let mut buffer = [0; 512];

stream.read(&mut buffer).unwrap();

println!("Request: {}", String::from_utf8_lossy(&buffer[..]));

let contents = "Hello World!";

let response = format!("HTTP/1.1 200 OK {}", contents);

stream.write(response.as_bytes()).unwrap();

stream.flush().unwrap();

}

我们直接编译执行程式:

cargo run

执行结果如下所示:

使用浏览器访问如下地址:http://127.0.0.1:7878/account_list/88 ,会显示Hello World资讯,这就说明我们的Web服务器可以正常运行了。

下面我们在handle_connection方法中,求出cmd引数的值,根据cmd呼叫不同的处理函式,在这些函式中呼叫Libra Core的区块链服务,解析区块链服务的返回结果,最后再以Http响应的形式返回给客户端。

我们要做的第一件事就是求出QueryString,程式码如下所示:

/**

* 获取请求中的Query String,规定引数以?cmd=开头

* @version v0.0.1 闫涛 2019.06.23

*/

fn get_query_string(request: &str) -> String {

let pos = request.find("?cmd=");

if pos return "Has no parameters in request".to_string();

}

let end_pos = request.find(" HTTP/1.1");

return (&request[(pos.unwrap()+1)..end_pos.unwrap()]).to_string();

}

在这段程式码中,我们首先找到QueryString开始位置,如果没找到则返回出错资讯。接着我们找到结束资讯,最后我们截取出子字串作为QueryString返回。

在得到QueryString之后,我们需要找出引数cmd的值,这样我们才能根据cmd引数的值呼叫对应的命令处理函式,如下所示:

/**

* 获取请求cmd引数值

* @version v0.0.1 闫涛 2019.06.23

*/

fn get_cmd_param(query_string: String) -> String {

let params: Vec = query_string.split("&").collect();

for param in params.iter() {

println!("item: {}!", param);

if param.find("cmd=") >= Some(0) {

let cmd = ¶m[4..];

return cmd.to_string();

}

}

return "".to_string();

}

接下来我们定义生成账户的命令处理函式,如下所示:

/**

* 生成账户命令处理函式

* @version v0.0.1 闫涛 2019.06.23

*/

fn handle_account_create(_params: Vec) -> String {

println!("生成新账户!");

let rst: String = String::from("create account: 0");

return rst;

}

实际中,这个函式需要呼叫Libra Core来建立账户,我们在这里先简单的返回一个字串,在下一篇文章中我们再来具体讲怎么呼叫Libra Core服务以及解析响应结果。

接下来我们看handle_connection方法,这时这个方法的逻辑就变为接到一个请求后,首先得到QueryString,然后从QueryString得到cmd引数,然后根据cmd的值呼叫对应的命令处理函式,如下所示:

fn handle_connection(mut stream: TcpStream) {

let mut contents: String = String::from("Hello World!");

let mut buffer = [0; 1024];

// 获取请求资讯

stream.read(&mut buffer).unwrap();

println!("Request: {}", String::from_utf8_lossy(&buffer[..]));

let request = String::from_utf8_lossy(&buffer[..]);

// 不处理请求网站图示请求

if request.find("GET /favicon.ico HTTP/1.1") >= Some(0) {

return ;

}

// 请出请求中的query string

let query_string = &get_query_string(&request);

println!("query_string:{}", query_string);

let cmd = get_cmd_param(query_string.to_string());

println!("接收到命令:cmd={}!", cmd);

let params: Vec = query_string.split("&").collect();

if cmd.find("account_create")>=Some(0) {

contents = handle_account_create(params);

} else if cmd.find("account_list")>=Some(0) {

contents = handle_account_list(params);

}

let response = format!("HTTP/1.1 200 OK {}", contents);

stream.write(response.as_bytes()).unwrap();

stream.flush().unwrap();

}

我们可以按照这种方式,将下列命令先以占位符的形式写出来,我在这里就不重复贴程式码了,在下一篇文章中,我们将对每个命令,学习怎样向Libra Core传送命令,以及怎样解析命令的返回结果。

2019-10-05 23:52:00

相关文章