嘛....html
注意:這裏是使用mongoose實現HTTP服務,非數據庫使用。ios
最近因爲須要使用HTTP服務端,原先是使用的Qt框架實現的HTTP服務端,而後發現有些缺陷致使我不得不放棄這個框架,也不是徹底放棄,只是HTTP服務端這裏再也不使用Qt,用Qt作高併發真的有點很差。web
而後毅然的選擇了mongoose這個框架,主要是據說這玩意 嵌入到代碼中很是方便。下載以後發現果真就一個 h文件和cpp文件。。數據庫
因而開始研究這個框架,根據mongoose 用戶手冊再加上一堆實例教程,基本上寫了一個類 進行操做封裝(並非徹底的封裝了)瀏覽器
MoHttp.h文件
主要是實現mongoose框架的基本 變量獲取。注意裏面有重載,主要是爲了方便使用。
#define _MOHTTP_H #ifdef _MOHTTP_H #include "mongoose.h" #include <iostream> using namespace std; const int CHAR_HTTP_VAR_MAX = 128; const int CHAR_HTTP_COOKIE_MAX = 400; class MoHttp { private: struct http_message *hm = NULL; public: MoHttp(struct http_message *); ~MoHttp(); int getGetVar(const char*, char*) const; //獲取變量 void getGetVar(const char*, string &) const; //獲取變量 int getPostVar(const char*, char*) const; //獲取變量 void getPostVar(const char*, string &) const; //獲取變量 int getCookie(const char*, char*) const; //獲取Cookie void getCookie(const char*, string &) const; //獲取Cookie int Model() const; //判斷當前模式 POST/GET 1爲 GET 不然爲0 }; #endif
MoHttp.cpp
實現各種方法。
#include "MoHttp.h" MoHttp::MoHttp(struct http_message * hm = NULL) { this->hm = hm; } int MoHttp::getGetVar(const char* name, char* var) const { memset(var, '\0', sizeof(var)); if (hm == NULL || name == NULL || hm->query_string.p == NULL)return -1; return mg_get_http_var(&hm->query_string, name, var, sizeof(var)); //獲取變量 } void MoHttp::getGetVar(const char* name, string & str) const { str = ""; char var[CHAR_HTTP_VAR_MAX]; var[0] = '\0'; if (hm == NULL || name == NULL || hm->query_string.p == NULL)return; mg_get_http_var(&hm->query_string, name, var, sizeof(var)); //獲取變量 if (var[0] == '\0'){ return; } str = var; //若是數據正確 } int MoHttp::getPostVar(const char* name, char* var) const { memset(var,'\0',sizeof(var)); if (hm == NULL || name == NULL || hm->body.p == NULL)return -1; return mg_get_http_var(&hm->body, name, var, sizeof(var)); //獲取變量 } void MoHttp::getPostVar(const char* name, string & str) const { str = ""; char var[CHAR_HTTP_VAR_MAX]; var[0] = '\0'; if (hm == NULL || name == NULL || hm->query_string.p == NULL)return; mg_get_http_var(&hm->body, name, var, sizeof(var)); //獲取變量 if (var[0] == '\0'){ return; } str = var; //若是數據正確 } int MoHttp::Model() const { if (hm == NULL || hm->method.p == NULL)return -1; //數據錯誤 if (mg_vcmp(&hm->method, "POST") != 0)return 1; return 0; } int MoHttp::getCookie(const char * name, char * var) const { memset(var, '\0', sizeof(var)); //mg_printf(nc, "Set-Cookie: %s=%s; path=/\r\n", "wwe", "123456789"); 發送Cookie if (hm == NULL) return -999; struct mg_str *cookie_header = mg_get_http_header(hm, "cookie"); //獲取Cookie 整條 if (cookie_header == NULL) return -999; //<0 return mg_http_parse_header(cookie_header, name, var, sizeof(var)); } void MoHttp::getCookie(const char* name, string & str) const { str = ""; char var[CHAR_HTTP_COOKIE_MAX]; //Cookie 最大更長 var[0] = '\0'; if (hm == NULL || name == NULL || hm->query_string.p == NULL)return; struct mg_str *cookie_header = mg_get_http_header(hm, "cookie"); //獲取Cookie 整條 if (cookie_header == NULL) return; mg_http_parse_header(cookie_header, name, var, sizeof(var)); if (var[0] == '\0'){ return; } str = var; //若是數據正確 } MoHttp::~MoHttp() { }
使用方法:服務器
Mo.cpp(或Main.cpp)websocket
// Copyright (c) 2016 by Suwings // All rights reserved #include <iostream> #include "MoHttp.h" using namespace std; static char *s_http_port = "23333"; static struct mg_serve_http_opts s_http_server_opts; MoHttp * mo = NULL; static void ev_handler(struct mg_connection *nc, int ev, void *p) { if (ev == MG_EV_HTTP_REQUEST) { //若是是HTTP 請求 struct http_message *hm = (struct http_message *) p; //傳爲 mo = new MoHttp(hm); //記得釋放內存,實例化 MoHttp if (mo->Model()==1){ //GET string w; //測試代碼 mo->getGetVar("user",w); //測試代碼 if (w != "")cout << "變量:" << w.c_str() << endl; //測試代碼 }else{ //測試代碼 //POST } //測試代碼 delete mo; //釋放變量 mg_serve_http(nc, hm, s_http_server_opts); //數據發送 } } int main(void) { struct mg_mgr mgr; struct mg_connection *nc; //struct mg_request_info *ww; mg_mgr_init(&mgr, NULL); printf("[狀態] 服務器已經開啓在端口: %s\n", s_http_port); nc = mg_bind(&mgr, s_http_port, ev_handler); if (nc == NULL) { printf("Failed to create listener\n"); return 1; } // Set up HTTP server parameters mg_set_protocol_http_websocket(nc); s_http_server_opts.document_root = "./www/"; // Serve current directory s_http_server_opts.enable_directory_listing = "no"; //Set if show dir for (;;) { mg_mgr_poll(&mgr, 1000); } mg_mgr_free(&mgr); return 0; }
看了幾個小時以後,差很少只能寫出這麼點東西了。而後我就一直在想。cookie
可是你有沒有發現,若是瀏覽器要是發送 Ajax 數據過來,假定邏輯在 C++ 代碼裏面,我應該如何設置返回的數據啊?session
的確,這個類也沒有加入 返回的數據,這個問題我也一直在困擾。併發
難道mongoose 框架都沒有函數是能夠設置數據在 body 的?百思不得其解的我因而去找了一下 mongoose 文檔裏面的例子,發現了一個Cookie驗證的例子,本來我覺得無論怎麼樣也會有設置數據的地方了,可是我驚奇的發現,是這樣的:
Cookie_auth.c 例子文件
static void set_session_cookie(struct mg_connection *nc, const struct session *s) { mg_printf(nc, "Set-Cookie: %s=%" INT64_X_FMT "; path=/\r\n", SESSION_COOKIE_NAME, s->id); } /* * If requested via GET, serves the login page. * If requested via POST (form submission), checks password and logs user in. */ static void login_handler(struct mg_connection *nc, int ev, void *p) { //主要看這個函數 struct http_message *hm = (struct http_message *) p; if (mg_vcmp(&hm->method, "POST") != 0) { /* Serve login.html */ mg_serve_http(nc, (struct http_message *) p, s_http_server_opts); } else { /* Perform password check. */ char user[50], pass[50]; int ul = mg_get_http_var(&hm->body, "user", user, sizeof(user)); int pl = mg_get_http_var(&hm->body, "pass", pass, sizeof(pass)); if (ul > 0 && pl > 0) { //若是有數據 if (check_pass(user, pass)) { //驗證帳號和密碼 函數無須理會 struct session *s = create_session(user, hm); //mg_printf 是直接輸出數據,並非輸出到body mg_printf(nc, "HTTP/1.0 302 Found\r\n"); set_session_cookie(nc, s); //他是進行了一次跳轉,而且直接返回的HTTP頭 mg_printf(nc, "Location: /\r\n"); mg_printf(nc, "\r\nHello, %s!\r\n", s->user); //這句是控制檯輸出 fprintf(stderr, "%s logged in, sid %" INT64_X_FMT "\n", s->user, s->id); } else { mg_printf(nc, "HTTP/1.0 403 Unauthorized\r\n\r\nWrong password.\r\n"); } } else { mg_printf(nc, "HTTP/1.0 400 Bad Request\r\n\r\nuser, pass required.\r\n"); } nc->flags |= MG_F_SEND_AND_CLOSE; } (void) ev; }
看完了以後我就跟納悶了,爲何要直接輸出HTTP頭?框架難道真的沒有提供相似的方法嗎?
而後嘗試了各種函數:
也無果,這些函數會 輸出到 HTTP 響應頭以前。
因此,是否是這個框架真的沒有 什麼設置返回的body 的函數呢?
總之目前只學到這裏,也許有什麼地方確實沒有了解。暫且先記錄下來,等知道了以後再續寫。