上一篇讲到简单的web server,控灯是靠网页的动作action来进行操作的,主要是应用的HTTP的get 请求方法,如果你需要传输数据get请求方法似乎就不够用了,所以换成post请求传输数据。传输少量数据并没有什么问题,但要是大量数据需要对LWIP的函数进行深挖才能进行大量数据的全部解析,本人在解析了几K数据之后wireshark,再大的数据仍然接收不了,且解析数据包复杂繁琐,所以放弃这个方法。
const unsigned char htmldata[] = "HTTP/1.1 200 OK\r\nContent-type:text/html\r\n\r\n\
<html> \
<head><title> A LwIP WebServer !!</title></head> \
<center>A WebServer Based on LwIP v1.4.1!</center>\
</html>";
const static char http_html_hdr_len_with_body[] = "HTTP/1.1 200 OK\r\nContent-type:text/html\r\n\
Content-Length: %d\r\n\
\r\n%s";
const static char http_ota[] = "\
<html>\r\n\
<head>\r\n\
<title>UploadFiles</title>\r\n\
</head>\r\n\
<body>\r\n\
<form action=\"ota\" method=\"post\" enctype=\"multipart/form-data\">\r\n\
<p><input type=\"file\" name=\"upload\"></p>\r\n\
<p><input type=\"submit\" value=\"submit\"></p>\r\n\
</form>\r\n\
</body>\r\n\
</html>";
static u8 key_push_down = false;
static void key_down_isr(void *context) //gpio中断
{
key_push_down = true;
}
void httpserver_send_html(struct tcp_pcb *pcb)
{
err_t err;
char * p_out = NULL;
// p_out = wl_zmalloc( 1500 );
// if( p_out == NULL ) {
//
// printf("malloc failed");
// }
//sprintf( p_out, http_html_hdr_len_with_body, strlen(http_ota), http_ota );
err = tcp_write(pcb, http_ota, sizeof(http_ota), 1);
if(err != ERR_OK) {
printf("write err!\n");
}
err = tcp_output(pcb);
if(err != ERR_OK) {
printf("output err!\n");
}
printf("%s,%d\n",__func__,__LINE__);
}
static bool end_signal = FALSE;
static err_t http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
struct pbuf *q;
q = p;
static int count = 0;
char * buf_user = NULL;
buf_user = wl_zmalloc(2048);
if( buf_user == NULL )
{
printf("malloc failed");
}
uint16_t cnt = 0;
char *temp_data = NULL;
char *data = NULL;
printf("%s,%d\n",__func__,__LINE__);
/* We perform here any necessary processing on the pbuf */
if (p != NULL) {
/* We call this function to tell the LwIp that we have processed the data */
/* This lets the stack advertise a larger window, so more data can be received*/
tcp_recved(pcb, p->tot_len);
end_signal = TRUE;
printf("%s,%d, tot_len = %d\n",__func__,__LINE__, p->tot_len);
data = p->payload;
temp_data = p->payload;
if(p->len >=5 && (strncmp(data, "GET /", 5) == 0)) {
httpserver_send_html(pcb);
printf("%s,%d\n",__func__,__LINE__);
} else if (p->len >= 8 && (strncmp(data, "POST /ota", strlen( "POST /ota" )) == 0)) {
httpserver_send_html(pcb);
memcpy( buf_user+cnt, temp_data, strlen(temp_data));
cnt += strlen(temp_data);
printf("data length : %d\n", strlen(temp_data));
temp_data = p->next->payload;
q = q->next; /
memcpy( buf_user+cnt, temp_data, strlen(temp_data));
printf("data length 2 : %d\n", strlen(temp_data));
// cnt += strlen(temp_data);
// temp_data = q->payload;
// memcpy( buf_user+cnt, temp_data, strlen(temp_data));
printf("upload\n");
printf("------------- POST INFORMATION -------------\n");
printf("-------------\n%s\n-------------\n", buf_user);
if( buf_user != NULL ) {
wl_free( buf_user );
buf_user = NULL;
}
//count++;
} else {
printf("------------- FILE RECEIVE -------------\n");
do {
memcpy( buf_user+cnt, temp_data, strlen(temp_data));
printf("data length : %d\n", strlen(temp_data));
cnt += strlen(temp_data);
temp_data = q->next->payload;
q = q->next;
} while (q != NULL);
// memcpy( buf_user+cnt, temp_data, strlen(temp_data));
// printf("data length 1: %d\n", strlen(temp_data));
// cnt += strlen(temp_data);
// temp_data = p->next->payload;
// memcpy( buf_user+cnt, temp_data, strlen(temp_data));
// printf("data length 2: %d\n", strlen(temp_data));
// q = q->next;
// cnt += strlen(temp_data);
// temp_data = q->payload;
// memcpy( buf_user+cnt, temp_data, strlen(temp_data));
// printf("data length 3: %d\n", strlen(temp_data));
printf("------------- data -------------\n");
printf("-------------\n%s\n-------------\n", buf_user);
if( buf_user != NULL ) {
wl_free( buf_user );
buf_user = NULL;
}
}
//pbuf_free(p);
//tcp_close(pcb);
} else if (err == ERR_OK) {
/* When the pbuf is NULL and the err is ERR_OK, the remote end is closing the connection. */
/* We free the allocated memory and we close the connection */
pbuf_free(p);
printf("--------------- receive over -------------------\n");
return tcp_close(pcb);
}
return ERR_OK;
}
static err_t http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
tcp_recv(pcb, http_recv);
return ERR_OK;
}
static void web_server_init(void)
{
struct tcp_pcb *pcb = NULL;
pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, 80);
pcb = tcp_listen(pcb);
tcp_accept(pcb, http_accept);
}
void server_task(void *context)
{
gpio_init();
while(!key_push_down){
wl_os_mdelay(1000);
}
printf("web server start \n");
web_server_init();
}
void server_entry(void)
{
wl_create_thread("webserver thread", 512, MAIN_TASK_PRIO, (thread_func_t)server_task, NULL);
}
注意:1.最好学习一下http,html相关,网页数组,可以用字符串,也可以用网页文件转成的十六进制数组,转换工具可以网上自行搜索
2.大数据接收时,表面上tcp_recved(pcb, p->tot_len)只接受了一部分数据,上一篇netbuf_data(inbuf, (void**)&buf, &buflen)也是一样,一个大数据包过来,会进行分包,分包接收之后,要想解析完整数据需要进行指针移动p,netbuf_data要和netbuf_next配合使用才能完全解析