Fourshortwordssumupwhathasliftedmostsuccessfulindividualsabovethecrowd:alittlebitmore.------------------------------------------author------------------------------------------datelwip1.4.0之http-server实现及POST-实现lwip1.4.0之http-server实现及POST-实现lwip1.4.0之http-server实现及POST-实现----------------------------------------------------------------------------------------------------lwip1.4.0之http-server实现及POST-实现--------------------------------------------------lwip1.4.0之http server实现及POST 实现 一、HTTP SERVER的实现 lwip默认的http server 在 apps/httpserver_raw 主要核心文件为 fs.c fs.h(读取相关html相关资源), httpd.c httpd.h httpd_structs.h 为http协议核心文件 首先在LWIP协议栈正常运行后 需要在main函数中调用httpd_init() 初始化Http 正常情况下般还需要实现SSI和CGI回调函数的初始工作 本人写在一个函数中 如下:void http_start(void){ http_set_ssi_handler(SSIHandler, g_pcConfigSSITags, sizeof(g_pcConfigSSITags)/sizeof (char *)); http_set_cgi_handlers(g_psConfigCGIURIs, sizeof(g_psConfigCGIURIs)/sizeof(tCGI));}然在httpd_init()下调用http_start() 完成初始化SSI和CGI的工作。 其次 要使用makefsfile.exe 对网页进行编译 这个小工具可以从网上下载一个, 本人将编译命令写在一个makefsfile.bat批处理文件中 每次编译只要运行一下makefsfile.bat 具体命令如下: echo offmakefsfile -i web_pages -o ../lwip-1.4.0/src/apps/httpserver_raw/fsdata.h -r -hecho on 其中 web_pages为所包含的网页文件夹 产生的网页数据放在fsdata.h中 用于跟
文件一起编译, -r 表示每次编译网页时重写fsdata.h -h 表示产生的网页数据中不包含http协议头部 因为本人在HTTP中使用的是动态产生HTTP协议头。 至此 网页完成 在浏览器中敲入板子的IP地址 便可以看到网页了 二、POST
实现LWIP HTTP 协议中默认只支持GET方法 但是一般提交表单时都用POST方法 而LWIPPOST方案需要自己实现 不过LWIP已经需要实现的函数申明在httpd.h中了首先将宏 LWIP_HTTPD_SUPPORT_POST 设置成1 表示支持HTTP POST 方法, 需要实现的函数分别为: httpd_post_begin(当接收到一个POST请求时会调用此函数), httpd_post_receive_data(接收HTTP POST 数据), httpd_post_finished(接收完成后 调用此函数)具体实现如下:err_t httpd_post_begin(void *connection, const char *uri, const char *http_request, u16_t http_request_len, int content_len, char *response_uri, u16_t response_uri_len, u8_t *post_auto_wnd){#if LWIP_HTTPD_CGI int i = 0;#endifstruct http_state *hs = (struct http_state *)connection; if(!uri || (uri[0] == '\0')) { return ERR_ARG; } hs->cgi_handler_index = -1; // 此变量为本人自己在struct http_state 添加 用于保存CGI handler 索引 为-1表示无CGI handler索引 hs->response_file = NULL; // 此变量为本人自己在struct http_state 添加 用于保存 CGI handler 处理完后返回的响应uri. #if LWIP_HTTPD_CGI if (g_iNumCGIs && g_pCGIs) { for (i = 0; i < g_iNumCGIs; i++) { if (strcmp(uri, g_pCGIs[i].pcCGIName) == 0) { hs->cgi_handler_index = i; // 找到响应的 CGI handler 将其保存在cgi_handler_index 以便在httpd_post_receive_data中使用 break; } } } if(i == g_iNumCGIs) { return ERR_ARG; // 未找到CGI handler }#endif return ERR_OK;} #define LWIP_HTTPD_POST_MAX_PAYLOAD_LEN 512static char http_post_payload[LWIP_HTTPD_POST_MAX_PAYLOAD_LEN];static u16_t http_post_payload_len = 0; err_t httpd_post_receive_data(void *connection, struct pbuf *p){ struct http_state *hs = (struct http_state *)connection; struct pbuf *q = p; int count; u32_t http_post_payload_full_flag = 0; while(q != NULL) // 缓存接收的数据至http_post_payload { if(http_post_payload_len + q->len <= LWIP_HTTPD_POST_MAX_PAYLOAD_LEN) { MEMCPY(http_post_payload+http_post_payload_len, q->payload, q->len); http_post_payload_len += q->len; } else { // 缓存溢出 置溢出标志位 http_post_payload_full_flag = 1; break; } q = q->next; } pbuf_free(p); // 释放pbuf if(http_post_payload_full_flag) // 缓存溢出 则丢弃数据 { http_post_payload_full_flag = 0; http_post_payload_len = 0; hs->cgi_handler_index = -1; hs->response_file = NULL; } else if(hs->post_content_len_left == 0) { // POST数据已经接收完毕 则处理 if(hs->cgi_handler_index != -1) { count = extract_uri_parameters(hs, http_post_payload); // 解析 hs->response_file = g_pCGIs[hs->cgi_handler_index].pfnCGIHandler(hs->cgi_handler_index, count, hs->params, hs->param_vals); // 调用解析函数 http_post_payload_len = 0; } else { hs->response_file = NULL; http_post_payload_len = 0; } } return ERR_OK;} void httpd_post_finished(void *connection, char *response_uri, u16_t response_uri_len){ struct http_state *hs = (struct http_state *)connection; if(hs->response_file != NULL) { strncpy(response_uri, hs->response_file,response_uri_len); // 拷贝uri 用于给浏览器响应相应的请求 }} 至此 HTTP SERVER 和 HTTP POST 方法实现完成