上传个LwIP HttpClient源码(raw api)
上传个LwIP HttpClient源码(raw api),有K60板子移植LWip的可以试试本帖最后由 superrf 于 2014-12-31 11:59 编辑
/*
HTTP CLIENT FOR RAW LWIP
(c) 2008-2009 Noyens Kenneth
PUBLIC VERSION V0.2 16/05/2009
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1 as published by
the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the
Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <string.h>
#include "webclient.h"
#include "utils/ustdlib.h"
// Close a PCB(connection)
void hc_clearpcb(struct tcp_pcb *pcb)
{
if(pcb != NULL)
{
// Close the TCP connection
tcp_close(pcb);
}
}
// Function that lwip calls for handling recv'd data
err_t hc_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
struct hc_state *state = arg;
char * page = NULL;
struct pbuf * temp_p;
hc_errormsg errormsg = GEN_ERROR;
int i;
if((err == ERR_OK) && (p != NULL))
{
tcp_recved(pcb, p->tot_len);
// Add payload (p) to state
temp_p = p;
while(temp_p != NULL)
{
state->RecvData = realloc(state->RecvData, temp_p->len + state->Len + 1);
// CHECK 'OUT OF MEM'
if(state->RecvData == NULL)
{
// OUT OF MEMORY
(*state->ReturnPage)(state->Num, OUT_MEM, NULL, 0);
return(ERR_OK);
}
strncpy(state->RecvData + state->Len, temp_p->payload, temp_p->len);
state->RecvData = '\0';
state->Len += temp_p->len;
temp_p = temp_p->next;
}
// Removing payloads
while(p != NULL)
{
temp_p = p->next;
pbuf_free(p);
p = temp_p;
}
}
// NULL packet == CONNECTION IS CLOSED(by remote host)
else if((err == ERR_OK) && (p == NULL))
{
// Simple code for checking 200 OK
for(i=0; i < state->Len; i++)
{
if(errormsg == GEN_ERROR)
{
// Check for 200 OK
if((*(state->RecvData+i) == '2') && (*(state->RecvData+ ++i) == '0') && (*(state->RecvData+ ++i) == '0')) errormsg = OK;
if(*(state->RecvData+i) == '\n') errormsg = NOT_FOUND;
}
else
{
// Remove headers
if((*(state->RecvData+i) == '\r') && (*(state->RecvData+ ++i) == '\n') && (*(state->RecvData+ ++i) == '\r') && (*(state->RecvData + ++i) == '\n'))
{
i++;
page = malloc(strlen(state->RecvData+i));
strcpy(page, state->RecvData+i);
break;
}
}
}
if(errormsg == OK)
{
// Put recv data to ---> p->ReturnPage
(*state->ReturnPage)(state->Num, OK, page, state->Len);
}
else
{
// 200 OK not found Return NOT_FOUND (WARNING: NOT_FOUND COULD ALSO BE 5xx SERVER ERROR, ...)
(*state->ReturnPage)(state->Num, errormsg, NULL, 0);
}
// Clear the PCB
hc_clearpcb(pcb);
// free the memory containing state
free(state->RecvData);
free(state);
}
return(ERR_OK);
}
// Function that lwip calls when there is an error
static void hc_error(void *arg, err_t err)
{
struct hc_state *state = arg;
// pcb already deallocated
// Call return function
// TO-DO: Check err_t err for out_mem, ...
(*state->ReturnPage)(state->Num, GEN_ERROR, NULL, 0);
free(state->RecvData);
free(state->PostVars);
free(state->Page);
free(state);
}
// Function that lwip calls when the connection is idle
// Here we can kill connections that have stayed idle for too long
static err_t hc_poll(void *arg, struct tcp_pcb *pcb)
{
struct hc_state *state = arg;
state->ConnectionTimeout++;
if(state->ConnectionTimeout > 20)
{
// Close the connection
tcp_abort(pcb);
// Give err msg to callback function
// Call return function
(*state->ReturnPage)(state->Num, TIMEOUT, NULL, 0);
}
return(ERR_OK);
}
// lwip calls this function when the remote host has successfully received data (ack)
static err_t hc_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
struct hc_state *state = arg;
// Reset connection timeout
state->ConnectionTimeout = 0;
return(ERR_OK);
}
// lwip calls this function when the connection is established
static err_t hc_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct hc_state *state = arg;
char* headers;
// error?
if(err != ERR_OK)
{
hc_clearpcb(pcb);
// Call return function
(*state->ReturnPage)(state->Num, GEN_ERROR, NULL, 0);
// Free wc state
free(state->RecvData);
free(state);
return(ERR_OK);
}
// Define Headers
if(state->PostVars == NULL)
{
// GET headers (without page)(+ \0) = 19
headers = malloc(19 + strlen(state->Page));
usprintf(headers,"GET /%s HTTP/1.0\r\n\r\n", state->Page);
}
else
{
// POST headers (without PostVars or Page)(+ \0) = 91
// Content-length: %d <== ??? (max 10)
headers = malloc(91 + strlen(state->PostVars) + strlen(state->Page) + 10);
usprintf(headers, "POST /%s HTTP/1.0\r\nContent-type: application/x-www-form-urlencoded\r\nContent-length: %d\r\n\r\n%s\r\n\r\n", state->Page, strlen(state->PostVars), state->PostVars);
}
// Check if we are nut running out of memory
if(headers == NULL)
{
hc_clearpcb(pcb);
// Call return function
(*state->ReturnPage)(state->Num, OUT_MEM, NULL, 0);
// Free wc state
free(state->RecvData);
free(state);
return(ERR_OK);
}
// Setup the TCP receive function
tcp_recv(pcb, hc_recv);
// Setup the TCP error function
tcp_err(pcb, hc_error);
// Setup the TCP polling function/interval //TCP_POLL IS NOT CORRECT DEFINED @ DOC!!!
tcp_poll(pcb, hc_poll, 10);
// Setup the TCP sent callback function
tcp_sent(pcb, hc_sent);
// Send data
tcp_write(pcb, headers, strlen(headers), 1);
tcp_output(pcb);
// remove headers
free(headers);
free(state->PostVars); // postvars are send, so we don't need them anymore
free(state->Page); // page is requested, so we don't need it anymore
return(ERR_OK);
}
// Public function for request a webpage (REMOTEIP, ...
int hc_open(struct ip_addr remoteIP, char *Page, char *PostVars, void (* returnpage)(u8_t, hc_errormsg, char *, u16_t))
{
struct tcp_pcb *pcb = NULL;
struct hc_state *state;
static u8_t num = 0;
// local port
u16_t port= 4545;
// Get a place for a new webclient state in the memory
state = malloc(sizeof(struct hc_state));
// Create a new PCB (PROTOCOL CONTROL BLOCK)
pcb = tcp_new();
if(pcb == NULL || state == NULL)
{
//UARTprintf("hc_open: Not enough memory for pcb or state\n");
//Not enough memory
return 0;
}
// Define webclient state vars
num++;
state->Num = num;
state->RecvData = NULL;
state->ConnectionTimeout = 0;
state->Len = 0;
state->ReturnPage = returnpage;
// Make place for PostVars & Page
if(PostVars != NULL) state->PostVars = malloc(strlen(PostVars) +1);
state->Page = malloc(strlen(Page) +1);
// Check for "out of memory"
if(state->Page == NULL || (state->PostVars == NULL && PostVars != NULL))
{
free(state->Page);
free(state->PostVars);
free(state);
tcp_close(pcb);
return 0;
}
// Place allocated copy data
strcpy(state->Page, Page);
if(PostVars != NULL) strcpy(state->PostVars, PostVars);
// Bind to local IP & local port
while(tcp_bind(pcb, IP_ADDR_ANY, port) != ERR_OK)
{
// Local port in use, use port+1
port++;
}
// Use conn -> argument(s)
tcp_arg(pcb, state);
// Open connect (SEND SYN)
tcp_connect(pcb, &remoteIP, 80, hc_connected);
return num;
}
这代码惨不忍睹啊 好东西,最近有时间研究下远程控制的WEB方式! 头晕,这代码 使用范例
hc_open(*ipaddr, "/", NULL, page_recv);
void page_recv(u8_t num, hc_errormsg errormsg, char * page, u16_t len)
{
if(page) UARTprintf("%s\n\n\n", page);
else
{
UARTprintf("error: ");
if(errormsg == OUT_MEM) UARTprintf("OUT MEM");
else if(errormsg == TIMEOUT) UARTprintf("TIME OUT");
else if(errormsg == NOT_FOUND) UARTprintf("NO 200 OK");
else if(errormsg == GEN_ERROR) UARTprintf("GEN ERROR");
else UARTprintf("?? ERROR");
UARTprintf("\n");
}
}
nongxiaoming 发表于 2014-12-31 11:52
这代码惨不忍睹啊
怎么个惨不忍睹法?这个代码貌似是FSL配套例程。 fengyunyu 发表于 2014-12-31 12:47
怎么个惨不忍睹法?这个代码貌似是FSL配套例程。
我看的时候你没有排版,代码都没高亮,所以…… 学习tcpip中,感谢分享 手头上用的是STM32板子,不知道能否移植 chwe1112 发表于 2015-1-8 09:12
手头上用的是STM32板子,不知道能否移植
可以移植,只要剩余内存够就行 有没有应用例程 sober 发表于 2015-1-9 17:06
有没有应用例程
6楼就是使用范例 不错 ,lwip的移植,必须要有个带网络的板子才能跑起来 。 K60带网络功能,你的飞币快够了 superrf 发表于 2015-1-9 21:41
K60带网络功能,你的飞币快够了
是哦 ,等飞币够了换一块 。也把lwip移植进去 你好,有没有例程工程,许多库没有,是基于LWIP开发吗 sober 发表于 2015-1-12 16:00
你好,有没有例程工程,许多库没有,是基于LWIP开发吗
只要移植了LWIP就可用,目前还没有K60的工程呢。
#include "utils/lwiplib.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "ethernet.h"
在lwip中没有
sober 发表于 2015-1-12 16:26
#include "utils/lwiplib.h"
#include "inc/hw_memmap.h"
没有可用删掉,移植多少需要改动一部分代码 superrf 发表于 2015-1-12 16:35
没有可用删掉,移植多少需要改动一部分代码
谢谢楼主,我已移植成功,头文件需加
#include "lwip/pbuf.h"
#include "lwip/tcp.h" sober 发表于 2015-1-12 17:37
谢谢楼主,我已移植成功,头文件需加
#include "lwip/pbuf.h"
#include "lwip/tcp.h"
移植到哪个平台,K60还是STM32? superrf 发表于 2015-1-12 17:55
移植到哪个平台,K60还是STM32?
GD32F107,STM32F107,GD和ST通用 sober 发表于 2015-1-12 18:00
GD32F107,STM32F107,GD和ST通用
GD32F107什么价格?跟STM32F107兼容吗? superrf 发表于 2015-1-8 09:29
可以移植,只要剩余内存够就行
请教下Stm32f103ZET6可以么? 否则 是否可以加扩展存储器? 扬帆远航 发表于 2015-1-12 18:11
请教下Stm32f103ZET6可以么? 否则 是否可以加扩展存储器?
当然可以了,不需要扩展存储器 superrf 发表于 2015-1-12 18:18
当然可以了,不需要扩展存储器
谢谢,今天刚买的板子.. superrf 发表于 2015-1-12 18:03
GD32F107什么价格?跟STM32F107兼容吗?
GD32F107兼容STM32F107,GD比ST便宜,我们用样片进行开发,具体价格不太清楚 谢谢,回头试试 谢谢楼主,一直不知道raw lwip和带任务的有什么区别 本帖最后由 sober 于 2015-1-12 18:53 编辑
我的网络数据缓冲为512KB,LWIP我裁剪到10K,网络应用有TcpServer、UdpServer、HttpClient 楼主有做lwip的DNS吗 不错,待我下下来研究下 不错 ,LWIP协议栈 ,网络通信的好工具 ! benhaha 发表于 2015-1-12 18:45
谢谢楼主,一直不知道raw lwip和带任务的有什么区别
raw lwip 是裸的 。
带任务的就是带操作系统 ,常见ucos 2 扬帆远航 发表于 2015-1-12 18:11
请教下Stm32f103ZET6可以么? 否则 是否可以加扩展存储器?
Stm32f103ZET6 可以的,这个芯片不带MAC ,需要外接mac 和PHY ! qs6361036 发表于 2015-1-12 20:02
Stm32f103ZET6 可以的,这个芯片不带MAC ,需要外接mac 和PHY !
Stm32f103ZET6 通常外接ENC28J60 sober 发表于 2015-1-12 18:55
楼主有做lwip的DNS吗
lwip带DNS dns_gethostbyname("www.baidu.com", &resolved, dns_serverfound, NULL);
void dns_serverfound(const char *name, struct ip_addr *ipaddr, void *arg)
{
if ((ipaddr) && (ipaddr->addr))
{
// ipaddr->addr;
}
} 呵呵 k60有mqx有rtcs有webserver的,很容易就实现网页啦。 sblpp 发表于 2015-1-12 21:21
呵呵 k60有mqx有rtcs有webserver的,很容易就实现网页啦。
RTCS需要单独购买,lwip是开源的 superrf 发表于 2015-1-12 21:14
Stm32f103ZET6 通常外接ENC28J60
是的,外接ENC28J60 比较常见 ! superrf 发表于 2015-1-12 21:26
RTCS需要单独购买,lwip是开源的
谁说的?
rtcs集成在mqx里的
直接用就可以了。 sblpp 发表于 2015-1-12 21:55
谁说的?
rtcs集成在mqx里的
直接用就可以了。
能用不等于免费,盗版Windows也能免费用。
请看官网http://www.freescale.com/zh-Hans/webapp/sps/site/prod_summary.jsp?code=MQXIPV6&cof=1&am=0&nodeId=01521060795D90&tab=Buy_Parametric_Tab
人民币31,034.00 可以做https不 对内存要求多少? lininglive 发表于 2015-1-27 11:25
对内存要求多少?
取决于要处理网页请求大小和网页请求处理方法 不知道为什么RTCS这么贵,不知道FSL有没有便宜一点的解决方案。 这种小的web server没啥意思啊 Juggernaut 发表于 2015-1-27 15:39
这种小的web server没啥意思啊
这个是WebClient 可以连接服务器的 superrf 发表于 2015-1-27 15:48
这个是WebClient 可以连接服务器的
client还不错的{:lol:} qs6361036 发表于 2015-1-12 21:32
是的,外接ENC28J60 比较常见 !
enc28j60存在发送接收逻辑的bug,让我头疼了一阵子,现在已经解决了
页:
[1]