往期教程
如果覺得寫的可以,請給一個點(diǎn)贊+關(guān)注支持一下
觀看之前請先看,往期的博客教程,否則這篇博客沒辦法看懂
-
workFlow c++異步網(wǎng)絡(luò)庫編譯教程與簡介
-
C++異步網(wǎng)絡(luò)庫workflow入門教程(1)HTTP任務(wù)
-
C++異步網(wǎng)絡(luò)庫workflow系列教程(2)redis任務(wù)
-
workflow系列教程(3)Series串聯(lián)任務(wù)流
-
workflow系列教程(4)Parallel并聯(lián)任務(wù)流
-
workflow系列教程(5-1)HTTP Server
-
workflow系列教程(5-2)實(shí)現(xiàn)HTTP反向代理
處理請求
我們不占用任何線程讀取文件,而是產(chǎn)生一個異步的讀文件任務(wù),在讀取完成之后回復(fù)請求。
再次說明一下,我們需要把完整回復(fù)數(shù)據(jù)讀取到內(nèi)存,才開始回復(fù)消息。所以不適合用來傳輸太大的文件。
struct SeriesContext{
WFHttpTask *serverTask; //所屬workflow任務(wù)
int fd; //文件fd
char *buf; //文件數(shù)據(jù)緩沖區(qū)
size_t filesize; //文件大小
};
void process(WFHttpTask *serverTask){
// 1 創(chuàng)建文件IO任務(wù)
size_t filesize = 614;
int fd = open("postform.html",O_RDONLY);
char *buf = new char[filesize];
auto IOTask = WFTaskFactory::create_pread_task(fd,buf,filesize,0,IOCallback);
// 2 把文件IO任務(wù)加入到序列中
series_of(serverTask)->push_back(IOTask);
// 3 創(chuàng)建傳遞給IOTask的context
SeriesContext *context = new SeriesContext;
context->serverTask = serverTask;
context->fd = fd;
context->buf = buf;
context->filesize = filesize;
series_of(serverTask)->set_context(context);
// 4 設(shè)置序列的回調(diào)函數(shù),釋放所有資源
series_of(serverTask)->set_callback([](const SeriesWork *series){
fprintf(stderr,"series callback\n");
SeriesContext * context = static_cast<SeriesContext *>(series->get_context());
delete[] context->buf;
close(context->fd);
delete context;
});
}
與HTTP反向代理產(chǎn)生一個新的http client任務(wù)不同,這里我們通過factory產(chǎn)生了一個pread任務(wù)。
在WFTaskFactory.h里,我們可以看到相關(guān)的接口。
struct FileIOArgs
{
int fd;
void *buf;
size_t count;
off_t offset;
};
...
using WFFileIOTask = WFFileTask<struct FileIOArgs>;
using fio_callback_t = std::function<void (WFFileIOTask *)>;
...
class WFTaskFactory
{
public:
...
static WFFileIOTask *create_pread_task(int fd, void *buf, size_t count, off_t offset,
fio_callback_t callback);
static WFFileIOTask *create_pwrite_task(int fd, void *buf, size_t count, off_t offset,
fio_callback_t callback);
...
/* Interface with file path name */
static WFFileIOTask *create_pread_task(const std::string& pathname, void *buf, size_t count, off_t offset,
fio_callback_t callback);
static WFFileIOTask *create_pwrite_task(const std::string& pathname, void *buf, size_t count, off_t offset,
fio_callback_t callback);
};
無論是pread還是pwrite,返回的都是WFFileIOTask。這與不區(qū)分sort或psort,不區(qū)分client或server task是一個道理。
除這兩個接口還有preadv和pwritev,返回WFFileVIOTask,以及fsync,fdsync,返回WFFileSyncTask。可以在頭文件里查看。
示例用了task的user_data域保存服務(wù)的全局?jǐn)?shù)據(jù)。但對于大服務(wù),推薦使用series context。
處理讀文件結(jié)果及響應(yīng)
將文件資源返回給客戶端文章來源:http://www.zghlxwxcb.cn/news/detail-849516.html
void IOCallback(WFFileIOTask *IOTask){
SeriesContext *context = static_cast<SeriesContext *>(series_of(IOTask)->get_context());
auto resp2client = context->serverTask->get_resp();
resp2client->add_header_pair("Content-Type","text/html");
resp2client->append_output_body(context->buf,context->filesize);
}
完整代碼
postform.html文章來源地址http://www.zghlxwxcb.cn/news/detail-849516.html
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<form method="post" enctype="application/x-www-form-urlencoded">
<div>
<label for="username">username:</label>
<input type="text" name="username">
</div>
<div>
<label for="password">password:</label>
<input type="text" name="password">
</div>
<div class="button">
<button type="submit">Send your message</button>
</div>
</form>
</body>
</html>
#include "linuxheader.h"
#include <workflow/WFFacilities.h>
#include <workflow/WFHttpServer.h>
#include <workflow/HttpUtil.h>
static WFFacilities::WaitGroup waitGroup(1);
void sigHandler(int num){
waitGroup.done();
fprintf(stderr,"wait group is done\n");
}
struct SeriesContext{
WFHttpTask *serverTask;
int fd;
char *buf;
size_t filesize;
};
void IOCallback(WFFileIOTask *IOTask){
SeriesContext *context = static_cast<SeriesContext *>(series_of(IOTask)->get_context());
auto resp2client = context->serverTask->get_resp();
resp2client->add_header_pair("Content-Type","text/html");
resp2client->append_output_body(context->buf,context->filesize);
}
void process(WFHttpTask *serverTask){
// 1 創(chuàng)建文件IO任務(wù)
size_t filesize = 614;
int fd = open("postform.html",O_RDONLY);
char *buf = new char[filesize];
auto IOTask = WFTaskFactory::create_pread_task(fd,buf,filesize,0,IOCallback);
// 2 把文件IO任務(wù)加入到序列中
series_of(serverTask)->push_back(IOTask);
// 3 創(chuàng)建傳遞給IOTask的context
SeriesContext *context = new SeriesContext;
context->serverTask = serverTask;
context->fd = fd;
context->buf = buf;
context->filesize = filesize;
series_of(serverTask)->set_context(context);
// 4 設(shè)置序列的回調(diào)函數(shù),釋放所有資源
series_of(serverTask)->set_callback([](const SeriesWork *series){
fprintf(stderr,"series callback\n");
SeriesContext * context = static_cast<SeriesContext *>(series->get_context());
delete[] context->buf;
close(context->fd);
delete context;
});
}
int main(){
signal(SIGINT,sigHandler);
WFHttpServer server(process);
if(server.start(1234) == 0){
waitGroup.wait();
server.stop();
}
else{
perror("server start failed\n");
return -1;
}
return 0;
}
到了這里,關(guān)于workflow系列教程(6)實(shí)現(xiàn)靜態(tài)資源服務(wù)器的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!