superrf 发表于 2014-12-31 11:49:51

上传个LwIP HttpClient源码(raw api)

上传个LwIP HttpClient源码(raw api),有K60板子移植LWip的可以试试

superrf 发表于 2014-12-31 11:50:46

本帖最后由 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;
}

nongxiaoming 发表于 2014-12-31 11:52:30

这代码惨不忍睹啊

activeleo 发表于 2014-12-31 11:53:29

好东西,最近有时间研究下远程控制的WEB方式!

Juggernaut 发表于 2014-12-31 11:58:49

头晕,这代码

superrf 发表于 2014-12-31 12:18:31

使用范例
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");
        }
}

fengyunyu 发表于 2014-12-31 12:47:42

nongxiaoming 发表于 2014-12-31 11:52
这代码惨不忍睹啊

怎么个惨不忍睹法?这个代码貌似是FSL配套例程。

nongxiaoming 发表于 2014-12-31 13:17:23

fengyunyu 发表于 2014-12-31 12:47
怎么个惨不忍睹法?这个代码貌似是FSL配套例程。

我看的时候你没有排版,代码都没高亮,所以……

jinyi7016 发表于 2015-1-7 20:13:43

学习tcpip中,感谢分享

chwe1112 发表于 2015-1-8 09:12:08

手头上用的是STM32板子,不知道能否移植

superrf 发表于 2015-1-8 09:29:55

chwe1112 发表于 2015-1-8 09:12
手头上用的是STM32板子,不知道能否移植

可以移植,只要剩余内存够就行

sober 发表于 2015-1-9 17:06:15

有没有应用例程

superrf 发表于 2015-1-9 17:08:00

sober 发表于 2015-1-9 17:06
有没有应用例程

6楼就是使用范例

franki 发表于 2015-1-9 21:36:15

不错 ,lwip的移植,必须要有个带网络的板子才能跑起来 。

superrf 发表于 2015-1-9 21:41:09

K60带网络功能,你的飞币快够了

franki 发表于 2015-1-9 21:56:31

superrf 发表于 2015-1-9 21:41
K60带网络功能,你的飞币快够了

是哦 ,等飞币够了换一块 。也把lwip移植进去

sober 发表于 2015-1-12 16:00:02

你好,有没有例程工程,许多库没有,是基于LWIP开发吗

superrf 发表于 2015-1-12 16:03:01

sober 发表于 2015-1-12 16:00
你好,有没有例程工程,许多库没有,是基于LWIP开发吗

只要移植了LWIP就可用,目前还没有K60的工程呢。

sober 发表于 2015-1-12 16:26:13

#include "utils/lwiplib.h"

#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "ethernet.h"

在lwip中没有


superrf 发表于 2015-1-12 16:35:00

sober 发表于 2015-1-12 16:26
#include "utils/lwiplib.h"

#include "inc/hw_memmap.h"


没有可用删掉,移植多少需要改动一部分代码

sober 发表于 2015-1-12 17:37:38

superrf 发表于 2015-1-12 16:35
没有可用删掉,移植多少需要改动一部分代码

谢谢楼主,我已移植成功,头文件需加
#include "lwip/pbuf.h"
#include "lwip/tcp.h"

superrf 发表于 2015-1-12 17:55:57

sober 发表于 2015-1-12 17:37
谢谢楼主,我已移植成功,头文件需加
#include "lwip/pbuf.h"
#include "lwip/tcp.h"

移植到哪个平台,K60还是STM32?

sober 发表于 2015-1-12 18:00:36

superrf 发表于 2015-1-12 17:55
移植到哪个平台,K60还是STM32?

GD32F107,STM32F107,GD和ST通用

superrf 发表于 2015-1-12 18:03:08

sober 发表于 2015-1-12 18:00
GD32F107,STM32F107,GD和ST通用

GD32F107什么价格?跟STM32F107兼容吗?

扬帆远航 发表于 2015-1-12 18:11:33

superrf 发表于 2015-1-8 09:29
可以移植,只要剩余内存够就行

请教下Stm32f103ZET6可以么? 否则 是否可以加扩展存储器?

superrf 发表于 2015-1-12 18:18:21

扬帆远航 发表于 2015-1-12 18:11
请教下Stm32f103ZET6可以么? 否则 是否可以加扩展存储器?

当然可以了,不需要扩展存储器

扬帆远航 发表于 2015-1-12 18:21:46

superrf 发表于 2015-1-12 18:18
当然可以了,不需要扩展存储器

谢谢,今天刚买的板子..

sober 发表于 2015-1-12 18:38:36

superrf 发表于 2015-1-12 18:03
GD32F107什么价格?跟STM32F107兼容吗?

GD32F107兼容STM32F107,GD比ST便宜,我们用样片进行开发,具体价格不太清楚

powerk6 发表于 2015-1-12 18:44:26

谢谢,回头试试

benhaha 发表于 2015-1-12 18:45:53

谢谢楼主,一直不知道raw lwip和带任务的有什么区别

sober 发表于 2015-1-12 18:51:49

本帖最后由 sober 于 2015-1-12 18:53 编辑

我的网络数据缓冲为512KB,LWIP我裁剪到10K,网络应用有TcpServer、UdpServer、HttpClient

sober 发表于 2015-1-12 18:55:50

楼主有做lwip的DNS吗

lzl000 发表于 2015-1-12 19:46:23

不错,待我下下来研究下

qs6361036 发表于 2015-1-12 19:59:17

不错 ,LWIP协议栈 ,网络通信的好工具 !

qs6361036 发表于 2015-1-12 20:00:51

benhaha 发表于 2015-1-12 18:45
谢谢楼主,一直不知道raw lwip和带任务的有什么区别

raw lwip 是裸的 。
带任务的就是带操作系统 ,常见ucos 2

qs6361036 发表于 2015-1-12 20:02:21

扬帆远航 发表于 2015-1-12 18:11
请教下Stm32f103ZET6可以么? 否则 是否可以加扩展存储器?

Stm32f103ZET6 可以的,这个芯片不带MAC ,需要外接mac 和PHY !

superrf 发表于 2015-1-12 21:14:31

qs6361036 发表于 2015-1-12 20:02
Stm32f103ZET6 可以的,这个芯片不带MAC ,需要外接mac 和PHY !

Stm32f103ZET6 通常外接ENC28J60

superrf 发表于 2015-1-12 21:15:53

sober 发表于 2015-1-12 18:55
楼主有做lwip的DNS吗

lwip带DNS

superrf 发表于 2015-1-12 21:19:49

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;
        }
}

sblpp 发表于 2015-1-12 21:21:28

呵呵 k60有mqx有rtcs有webserver的,很容易就实现网页啦。

superrf 发表于 2015-1-12 21:26:13

sblpp 发表于 2015-1-12 21:21
呵呵 k60有mqx有rtcs有webserver的,很容易就实现网页啦。

RTCS需要单独购买,lwip是开源的

qs6361036 发表于 2015-1-12 21:32:53

superrf 发表于 2015-1-12 21:14
Stm32f103ZET6 通常外接ENC28J60

是的,外接ENC28J60 比较常见 !

sblpp 发表于 2015-1-12 21:55:48

superrf 发表于 2015-1-12 21:26
RTCS需要单独购买,lwip是开源的

谁说的?
rtcs集成在mqx里的
直接用就可以了。

superrf 发表于 2015-1-12 22:24:26

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

sober 发表于 2015-1-27 11:07:26

可以做https不

lininglive 发表于 2015-1-27 11:25:07

对内存要求多少?

superrf 发表于 2015-1-27 12:35:16

lininglive 发表于 2015-1-27 11:25
对内存要求多少?

取决于要处理网页请求大小和网页请求处理方法

浪里白条 发表于 2015-1-27 15:09:57

不知道为什么RTCS这么贵,不知道FSL有没有便宜一点的解决方案。

Juggernaut 发表于 2015-1-27 15:39:32

这种小的web server没啥意思啊

superrf 发表于 2015-1-27 15:48:53

Juggernaut 发表于 2015-1-27 15:39
这种小的web server没啥意思啊

这个是WebClient 可以连接服务器的

Juggernaut 发表于 2015-1-27 17:16:24

superrf 发表于 2015-1-27 15:48
这个是WebClient 可以连接服务器的

client还不错的{:lol:}

lotoohe 发表于 2016-3-9 11:43:03

qs6361036 发表于 2015-1-12 21:32
是的,外接ENC28J60 比较常见 !

enc28j60存在发送接收逻辑的bug,让我头疼了一阵子,现在已经解决了
页: [1]
查看完整版本: 上传个LwIP HttpClient源码(raw api)