Skip to content

Commit

Permalink
add en doc
Browse files Browse the repository at this point in the history
  • Loading branch information
fawdlstty committed May 7, 2022
1 parent 18346eb commit 578cdec
Show file tree
Hide file tree
Showing 3 changed files with 354 additions and 74 deletions.
151 changes: 77 additions & 74 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,183 +1,186 @@
# libfv

libfv 是 C++20 纯头文件网络库,支持 TCP、SSL、Http1.1、websocket
English | [简体中文](./README.zh.md)

你可以通过它使用纯异步的网络功能,当然你也能完全不使用网络,仅使用异步包装功能,让你的项目支持异步开发。
libfv is C++20 header-only network library, support TCP, SSL, Http1.1, websocket

库除了提供网络功能外,还提供多种异步工具,比如定时器、信号量等。
You can use pure asynchronous networking with it, or you can use asynchronous wrappers without networking at all and support asynchronous development in your projects.

## 配置环境
In addition to providing network functions, the library also provides a variety of asynchronous tools, such as timers, semaphores, etc.

1. 配置 `vcpkg` 环境
## Started

1. config `vcpkg` environment (example system: Windows)
```
vcpkg install boost-asio:x86-windows-static
vcpkg install nlohmann-json:x86-windows-static
vcpkg install gzip-hpp:x86-windows-static
vcpkg install openssl:x86-windows-static
```
2. 初始化
2. Initialize
```cpp
// 任一一个cpp文件引入一次这个头文件(最好是空cpp文件)
// Any cpp file imports this header once (preferably an empty cpp file)
#include <fv/fv-impl.hpp>

// 在需要使用api的源码文件里引入库头文件
// Import library header files in source files that need to use the API
#include <fv/fv.hpp>

// 主函数
// Main function
int main () {
// 全局初始化
// Global initialize
fv::Tasks::Start (true);

// ...

// 全局释放
// Global release
fv::Tasks::Stop ();
return 0;
}
```
3. 调用异步函数时,通过 `fv::Tasks::RunAsync` 将其加入异步任务队列
3. When an asynchronous function has called, it is added to the task pool with 'fv::Tasks::RunAsync'
```cpp
// 异步函数
// Asynchronous function
Task<void> async_func () {
fv::Response _r = co_await fv::Post ("https://t.cn", fv::body_kv ("a", "aaa"));
std::cout << _r.Content;
}
// 带参异步函数
// Asynchronous function with parameter
Task<void> async_func2 (int n) {
std::cout << n << std::endl;
co_return;
}

// 执行异步函数,可以把 std::function<Task<void> ()> 类型方法塞进去
// To execute asynchronous functions, you can transfer std::function<Task<void> ()> type
fv::Tasks::RunAsync (async_func);
fv::Tasks::RunAsync (async_func2, 5);
```

现在我们已经创建好了异步函数环境,可以自由在里面编写异步代码啦!
Now that we have created the asynchronous function environment, we can write asynchronous code in it.

## 使用手册
## Manual

### 全局配置设置
### Global configuration Settings

```cpp
// 设置SSL校验函数(默认不校验)
// Set SSL verification function (default no verification)
fv::Config::SslVerifyFunc = [] (bool preverified, fv::Ssl::verify_context &ctx) { return true; };

// 设置全局TCP不延迟发送(对实时性要求较高场合使用)
// Setting global TCP transmission without delay (Used in scenarios requiring high real-time performance)
fv::Config::NoDelay = true;

// 设置全局 http 头(客户端)
// Setting the global HTTP header (client)
fv::Request::SetDefaultHeader ("User-Agent", "libfv-0.0.1");
```
### HTTP(S) Client
共支持6种HTTP请求,可使用 `fv::Head`、`fv::Option`、`fv::Get`、`fv::Post`、`fv::Put`、`fv::Delete` 方法。
A total of six HTTP requests are supported. You can use `fv::Head`、`fv::Option`、`fv::Get`、`fv::Post`、`fv::Put`、`fv::Delete` methods.
```cpp
// 发起 HttpGet 请求
// Send HttpGet request
fv::Response _r = co_await fv::Get ("https://t.cn");
// 发起 HttpPost 请求,提交 application/json 格式
// Send HttpPost request with `application/json` content type (default)
fv::Response _r = co_await fv::Post ("https://t.cn", fv::body_kv ("a", "aaa"));
// 发起 HttpPost 请求,提交 application/x-www-form-urlencoded 格式
// Send HttpPost request with `application/x-www-form-urlencoded` content type
fv::Response _r2 = co_await fv::Post ("https://t.cn", fv::body_kv ("a", "aaa"), fv::content_type ("application/x-www-form-urlencoded"));
// 提交文件
// Commit file
fv::Response _r = co_await fv::Post ("https://t.cn", fv::body_file ("a", "filename.txt", "content..."));
// 发起 HttpPost 请求并提交原始内容
// Send HttpPost request with raw data
fv::Response _r = co_await fv::Post ("https://t.cn", fv::body_raw ("application/octet-stream", "aaa"));
// 指定请求超时时长
// Specifies the request timeout period
fv::Response _r = co_await fv::Get ("https://t.cn", fv::timeout (std::chrono::seconds (10)));
// 向指定服务器发起请求
// Send request to the specified server
fv::Response _r = co_await fv::Get ("https://t.cn", fv::server ("106.75.237.200"));
// 自定义http头
// Custom http header
fv::Response _r = co_await fv::Get ("https://t.cn", fv::header ("X-WWW-Router", "123456789"));
// 设置http头 `Authorization` 值之 jwt bearer 鉴权
// Set http header `Authorization` value with jwt bearer authorization
fv::Response _r = co_await fv::Get ("https://t.cn", fv::authorization ("Bearer XXXXXXXXXXXXX=="));
// 设置http头 `Authorization` 值之用户名密码鉴权
// Set http header `Authorization` value with username and password
fv::Response _r1 = co_await fv::Get ("https://t.cn", fv::authorization ("admin", "123456"));
// 设置http头 `Connection`
// Set http header `Connection` value
fv::Response _r = co_await fv::Get ("https://t.cn", fv::connection ("keep-alive"));
// 设置http头 `Content-Type`
// Set http header `Content-Type` value
fv::Response _r = co_await fv::Get ("https://t.cn", fv::content_type ("application/octet-stream"));
// 设置http头 `Referer`
// Set http header `Referer` value
fv::Response _r = co_await fv::Get ("https://t.cn", fv::referer ("https://t.cn"));
// 设置http头 `User-Agent`
// Set http header `User-Agent` value
fv::Response _r = co_await fv::Get ("https://t.cn", fv::user_agent ("Mozilla/4.0 Chrome 2333"));
```

### Websocket Client

```cpp
// 建立链接
// Create connect
std::shared_ptr<fv::WsConn> _conn = co_await fv::ConnectWS ("wss://t.cn/ws");

// 循环接收内容并打印(抛异常说明链接断开)
// 能接收到三种类型,fv::WsType::Textfv::WsType::Binaryfv::WsType::Pong
// Loop to receive content and print (throw exception means link is broken)
// It can receive three types, `fv::WsType::Text`, `fv::WsType::Binary`, `fv::WsType::Pong`
while (true) {
auto [_data, _type] = co_await _conn->Recv ();
std::cout << _data << std::endl;
}

// 发送数据(抛异常说明链接断开)
// Send data (throw exception means link is broken)
std::string _str = "hello";
co_await _conn->SendText (_str.data (), _str.size ());
co_await _conn->SendBinary (_str.data (), _str.size ());
co_await _conn->SendPing ();

// 关闭链接
// Close connect
co_await _conn->Close ();
```
### TCP/SSL Client
```cpp
// 建立链接(ssl链接可换成:ssl://127.0.0.1:1234
// Create connect (SSL link can be changed to: ssl://127.0.0.1:1234)
std::shared_ptr<fv::IConn> _conn = co_await fv::Connect ("tcp://127.0.0.1:1234");
// 接收内容并打印(抛异常说明链接断开)
// 备注:TCP与SSL均为流式协议,无法准确获取单个数据包长度,请自定格式指定长度信息
// 备注:ReadCount ReadCountVec 必须待接收到那么长数据之后才会返回
// Receive content and print (throw exception means link is broken)
// Note: TCP and SSL are streaming protocols, so the length of a single packet cannot be accurately obtained. Please specify the length in a customized format
// Note: ReadCount and ReadCountVec will not return until specified length data has been received
char _ch = co_await _conn->ReadChar ();
std::string _line = co_await _conn->ReadLine ();
std::string _buf = co_await _conn->ReadCount (1024);
std::vector<uint8_t> _buf2 = co_await _conn->ReadCountVec (1024);
// 发送数据(抛异常说明链接断开)
// Send data (throw exception means link is broken)
std::string _str = "hello";
co_await _conn->Send (_str.data (), _str.size ());
// 关闭链接
// Close connect
co_await _conn->Close ();
```

### HTTP Server (Websocket Server)

```cpp
// 服务器对象
// Server object
fv::HttpServer _server {};

// 指定 HTTP 请求处理回调
// Specifies the http request handling callback
_server.SetHttpHandler ("/hello", [] (fv::Request &_req) -> Task<fv::Response> {
co_return fv::Response::FromText ("hello world");
});

// 指定 websocket 请求处理回调
// Specifies the websocket request handling callback
_server.SetHttpHandler ("/ws", [] (fv::Request &_req) -> Task<fv::Response> {
// 检查是否为 websocket 请求
// Check whether it is a websocket request
if (_req.IsWebsocket ()) {
// 升级为 websocket
// Upgrade to websocket connect
auto _conn = co_await _req.UpgradeWebsocket ();
while (true) {
auto [_data, _type] = co_await _conn->Recv ();
Expand All @@ -187,78 +190,78 @@ _server.SetHttpHandler ("/ws", [] (fv::Request &_req) -> Task<fv::Response> {
co_await _conn->SendBinary (_data.data (), _data.size ());
}
}
// 请求完成 websocket 升级后返回空即可
// Return empty after websocket upgrade
co_return fv::Response::Empty ();
} else {
co_return fv::Response::FromText ("please use websocket");
}
});

// 设置前置请求过滤(可不设置)
// Set before-request filtering (optional)
_server.OnBefore ([] (fv::Request &_req) -> std::optional<Task<fv::Response>> {
// 此处返回 std::nullopt 代表不做过滤,否则代表过滤请求(不进入 SetHttpHandler 处理回调)
// Return std::nullopt to indicate passing, otherwise intercept and return the currently returned result (Do not enter SetHttpHandler handling callback)
co_return std::nullopt;
});

// 设置后置请求过滤(可不设置)
// Set after-request filtering (optional)
_server.OnAfter ([] (fv::Request &_req, fv::Response &_res) -> Task<void> {
// 此处可对返回内容做一些处理
// Here you can do something with the returned content
co_return std::nullopt;
});

// 设置未 handle 的请求处理函数(可不设置)
// Set unhandled request handling callback (optional)
_server.OnUnhandled ([] (fv::Request &_req) -> Task<fv::Response> {
co_return fv::Response::FromText ("not handled!");
});

// 开始监听
// Start listen
co_await _server.Run (8080);
```

### TCP Server

```cpp
// 服务器对象
// Server object
TcpServer m_tcpserver {};

// 设置新链接处理函数
// Sets the new link handler function
m_tcpserver.SetOnConnect ([&m_tcpserver] (std::shared_ptr<IConn> _conn) -> Task<void> {
// 此处自由发挥,退出函数则链接断开,通常 while (true)
// Free play here, return then link close, usually `while (true)`

// 可考虑注册客户端及取消注册,此处自己根据业务指定ID
// You can register client or unregister, specify the ID based on your profession
m_tcpserver.RegisterClient (123, _conn);
m_tcpserver.UnregisterClient (123, _conn);
});

// 假如处理函数内部注册后,外部可直接给对应客户端发消息或者广播消息
// If the handler function has registered internally, the external can send or broadcast messages directly to the corresponding client
std::string _data = "hello";
co_await m_tcpserver.SendData (123, _data.data (), _data.size ());
co_await m_tcpserver.BroadcastData (_data.data (), _data.size ());

// 开始监听
// Start listen
co_await m_tcpserver.Run (2233);
```

## 附带的其他异步功能
## Another asynchronous functionality

```cpp
// 暂停 10
// Sleep 10 seconds
co_await fv::Tasks::Delay (std::chrono::seconds (10));

// 外部需要用到 io_context
// If external needs io_context
boost::asio::io_context &_ctx = fv::Tasks::GetContext ();

// 异步方法内同步
// 创建信号量
// Synchronization within asynchronous methods
// Create semaphore
AsyncSemaphore _sema { 1 };
// 尝试等待信号
// Attempt to acquire signal
bool _success = _sema.TryAcquire ();
// 异步等待信号
// Asynchronous wait signal
co_await _sema.AcquireAsync ();
// 超时异步等待信号
// Timeout asynchronously waits for a signal
bool _success = co_await _sema.AcquireForAsync (std::chrono::seconds (10));
bool _success = co_await _sema.AcquireForAsync (std::chrono::system_clock::now () + std::chrono::seconds (10));
// 释放信号
// Release signal
_sema.Release ();
```
Expand Down
Loading

0 comments on commit 578cdec

Please sign in to comment.