WIZnet Developer Forum

W5500 httpclient get file download

httpclient 파일 다운로드를 테스트중에 있습니다.
데이터 다운로드중 항상 일정 양의 데이터를(1~2Kbyte) 남기고 소켓이 SOCK_CLOSE_WAIT 되어 데이터 전부를 받아오지 못하는 현상이 발생합니다.
설정쪽에 문제인거 같은데 어디부분을 확인하면 될까요?

도움부탁드립니다.

//test code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>

#include "stm32f4xx_hal.h"

#include "HAL_Config.h"

#include "W5x00RelFunctions.h"

#include "MQTTClient.h"

#include "dns.h"

#include "wizchip_conf.h"

#include "socket.h"

#include "httpClient.h"

#include "w5500_control.h"

#include "lib_stdxx.h"

#include "m95m02_hal_spi.h"

#include "key.h"

#include "common.h"

#include "user_conf.h"

#include "dhcp.h"

#include "SSLInterface.h"

  

void log_net(char *log);    

 

void func_pack_http_get_download_header(uint8_t* buff, uint16_t size_buff, uint8_t* srv_ip, uint16_t srv_port, char* interface);

uint8_t func_http_get_download_file(uint8_t sockno, uint8_t* srv_ip, uint16_t srv_port, char* interface, uint16_t timeout_ms, uint8_t* buff, uint16_t size_buff);

uint8_t func_analysis_http_download_header(uint8_t* buffer, uint16_t len_buf, uint8_t *resp_code, uint8_t *is_stream, uint32_t *cont_len);

 

uint8_t buf[2048];

int httpclient_get_test(void)

{   

    //FIXME input your server ip to download file

    uint8_t srv_ip[] = {192, 168, 1, 2};

    uint16_t srv_port = 8000;

        

    setRTR(5000);

    setRCR(3);

    

    // HAL_Delay(100);

    

    //DHCP

    // for(;func_dhcp_get_ip_sub_gw(1, mac, &dhcp_get, 500) != 0;); 

    // if(func_dhcp_get_ip_sub_gw(1, mac, &dhcp_get, 500) == 0)

    // {

    //  setSUBR(dhcp_get.sub);

    //  setGAR(dhcp_get.gw);

    //  setSIPR(dhcp_get.lip);

    //  close(1);

        

    //  log_net("0");

    // }

    

    memset(buf, 0 , sizeof(buf));

    func_http_get_download_file(1, srv_ip, srv_port, "/4096.bin", 10000, buf, sizeof(buf));

    

    for(;;)

    {

//      func_led1_toggle();

        HAL_Delay(500); 

    }

}

 

uint8_t func_http_get_download_file(uint8_t sockno, uint8_t* srv_ip, uint16_t srv_port, char* interface, uint16_t timeout_ms, uint8_t* buff, uint16_t size_buff)

{

    uint16_t local_port = 60000, len = 0, cnt = 0;

    uint8_t sendok = 0, recv_start = 0;

    

    uint8_t cache[2048];

    uint16_t cache_cont_len;

    uint32_t cont_len, download_cont_len;

    

    func_pack_http_get_download_header(buff, size_buff, srv_ip, srv_port, interface);

    

//  setkeepalive(sockno);//auto

    IINCHIP_WRITE(Sn_KPALVTR(sockno),0x00);//manual

    

    memset(cache, 0 , sizeof(cache));

    cache_cont_len = 0;

    

    for(;;)

    {

        switch(getSn_SR(sockno))

        {

            case SOCK_INIT:

                    connect(sockno, srv_ip, srv_port);

            break;

            case SOCK_ESTABLISHED:

            {

                if(sendok == 0)

                {

                    log_net("1");

                    

                    len = strlen((char *)buff);

                    send(sockno, buff, len);

                    sendok ++;

                    if(getSn_IR(sockno) & Sn_IR_CON)                    

                    {

                        setSn_IR(sockno, Sn_IR_CON);

                        break;

                    }

                }

                

                len = getSn_RX_RSR(sockno);

                if(len > 0)

                {

                    cnt = 0;

                    

                    memset(buff, 0, size_buff);

                    len = recv(sockno, buff, len);

                    if(recv_start == 0)

                    {

                        uint8_t res, resp_code, isstream;

                        

                        log_net("2");

                        

                        if(cache_cont_len + len <= sizeof(cache))

                        {

                            log_net("3");

                            memcpy(cache+cache_cont_len, buff, len);

                            cache_cont_len += len;

                            

                            memset(buff, 0, size_buff);

                            len = 0;

                        }

                        else

                        {

                            uint32_t len_copy;

                            log_net("4");

                            

                            len_copy = sizeof(cache) - cache_cont_len;

                            memcpy(cache+cache_cont_len, buff, len_copy);

                            memcpy(buff, buff + len_copy, len - len_copy);

                            memset(buff + (len - len_copy), 0, size_buff - (len - len_copy));

                            len = len - len_copy;

                            cache_cont_len = sizeof(cache);

                            

                        }                           

                        

                        res = func_analysis_http_download_header(cache, cache_cont_len, &resp_code, &isstream, &cont_len);

                        if(res == 0)

                        {

                            if(resp_code != 200 || isstream != 1)//response code 200, must be iostream

                            {

                                log_net("22");

                                return 3;// response not ok

                            }

                            recv_start++;

                            

                            //logic -> file size should be no more than 108 Kbytes

                            if(cont_len > 108*1024)

                            {

                                log_net("23");

                                return 4;

                            }

                            

                            //if download file done

                            {

                                uint32_t tmp_len;

                                uint8_t* pos_header;

                                pos_header = (uint8_t*)strstr((char*)cache, "\r\n\r\n");

                                //remove header, save file byte to cache

                                tmp_len = cache_cont_len - (pos_header + 4 - cache);

                                memcpy(cache, pos_header + 4, tmp_len);

                                memset(cache + tmp_len, 0 , sizeof(cache) - tmp_len);

                                cache_cont_len = tmp_len;

                                download_cont_len = cache_cont_len;

                                

                                if(len > 0)

                                {

                                    if(cache_cont_len + len <= sizeof(cache))

                                    {

                                        log_net("5");

                                        memcpy(cache+cache_cont_len, buff, len);

                                        cache_cont_len += len;                                      

                                        download_cont_len += len;

                                        

                                        memset(buff, 0, size_buff);

                                        len = 0;

                                    }

                                    else

                                    {

                                        uint32_t len_copy;

                                        log_net("6");

                                        

                                        len_copy = sizeof(cache) - cache_cont_len;

                                        memcpy(cache+cache_cont_len, buff, len_copy);

                                        memcpy(buff, buff + len_copy, len - len_copy);

                                        memset(buff + (len - len_copy), 0, size_buff - (len - len_copy));

                                        len = len - len_copy;

                                        cache_cont_len = sizeof(cache);

                                        

                                        //TODO write to FLASH backup

                                        memset(cache, 0, cache_cont_len);

                                        cache_cont_len = 0;

                                        memcpy(cache+cache_cont_len, buff, len);

                                        cache_cont_len = len;

                                        download_cont_len = sizeof(cache) + cache_cont_len;

                                        

                                    }

                                }

                                

                                if(download_cont_len == cont_len)// small file download done

                                {

                                    log_net("7");

                                    //TODO write to FLASH backup and record

                                    

                                    disconnect(sockno);

                                    return 0;//download file done

                                }

                                

                            }                               

                        }

                    }

                    else

                    {

                        IINCHIP_WRITE(Sn_CR(sockno),Sn_CR_SEND_KEEP);//keep-alive manual

                        

                        //file size is big, write to FALSH several times

                        download_cont_len += len;

                        if(cache_cont_len + len <= sizeof(cache))

                        {

                            log_net("8");

                            memcpy(cache+cache_cont_len, buff, len);

                            cache_cont_len += len;

                            memset(buff, 0, size_buff);

                            len = 0;

                        }

                        else

                        {

                            uint32_t len_copy;

                            log_net("9");

                            len_copy = sizeof(cache) - cache_cont_len;

                            memcpy(cache+cache_cont_len, buff, len_copy);

                            memcpy(buff, buff + len_copy, len - len_copy);

                            memset(buff + (len - len_copy), 0, size_buff - (len - len_copy));

                            len = len - len_copy;

                            cache_cont_len = sizeof(cache);

                            

                            //TODO write to FLASH backup

                            // func_usart2_dma_send_bytes(cache, cache_cont_len);

                            memset(cache, 0, cache_cont_len);

                            cache_cont_len = 0;

                            memcpy(cache+cache_cont_len, buff, len);

                            cache_cont_len = len;

                        }                       

                        

                        //if donwload file done

                        if(download_cont_len == cont_len)

                        {

                            log_net("10");

                            //TODO write to FLASH backup and record

                            // func_usart2_dma_send_bytes(cache, cache_cont_len);

                            disconnect(sockno);

                            return 0;//download file done

                        }                           

                    }

                }

            }           

            break;

            case SOCK_CLOSE_WAIT:

                    close(sockno);

                    log_net("21");

                    return 2;//read timeout

            case SOCK_CLOSED:

                    close(sockno);

                    sendok = 0;

                    recv_start = 0;

                    if(local_port > 65400)

                    {

                        local_port = 60000;

                    }

                    socket(sockno, Sn_MR_TCP, local_port++, Sn_MR_ND);

            break;

        }

        

        cnt ++;

        if(cnt >= timeout_ms)

        {

            log_net("20");

            return 1;//connect timeout

        }

        HAL_Delay(1);

    }

}

 

uint8_t func_analysis_http_download_header(uint8_t* buffer, uint16_t len_buf, uint8_t *resp_code, uint8_t *is_stream, uint32_t *cont_len)

{

    *resp_code = 0;

    *is_stream = 0;

    *cont_len = 0;

    if(strstr((char*)buffer, "\r\n\r\n") != NULL)//response header ok

    {

        char *p1, *p2;

        

        p1 = strstr((char*)buffer, "HTTP/1.1 200"); 

        if(p1 != NULL)// io stream

        {

            *resp_code = 200;

        }       

        

        p1 = strstr((char*)buffer, "Accept-Ranges: bytes"); 

        if(p1 != NULL)// io stream

        {

            *is_stream = 1;

        }

        

        p1 = strstr((char*)buffer, "Content-Length: ");                                     

        if(p1 != NULL)

        {

            p2 = strstr(p1, "\r\n");

            if(p2 != NULL)

            {

                char str_len[8] = {0,};

                memcpy(str_len, p1 + strlen("Content-Length: "), p2 - p1 - strlen("Content-Length: "));

                *cont_len = atoi(str_len);

                return 0;

            }

        }

    }

    return 1;

}

 

void log_net(char *log)

{

    // uint8_t logsrv_ip[] = {192, 168, 1, 105};

    // socket(2, Sn_MR_UDP, 7890, 0x00);

    // sendto(2, (uint8_t*)log, strlen(log), logsrv_ip, 9876);

    DEBUG_PRINTF("%s\r\n", log);

}

 

void func_pack_http_get_download_header(uint8_t* buff, uint16_t size_buff, uint8_t* srv_ip, uint16_t srv_port, char* interface)

{

    uint8_t tmp[64];

    memset(buff, 0, size_buff);

    //header

    memcpy(buff, "GET ", strlen("GET "));

    strcat((char *)buff, interface);

    strcat((char *)buff, " HTTP/1.1\r\n");

    memset(tmp, 0 , sizeof(tmp));

    sprintf((char*)tmp, "Host: %d.%d.%d.%d:%d\r\n", srv_ip[0], srv_ip[1], srv_ip[2], srv_ip[3], srv_port);

    strcat((char *)buff, (char*)tmp);

    strcat((char *)buff, "Connection: Keep-Alive\r\n");

    strcat((char *)buff, "User-Agent: W5500\r\n");

    strcat((char *)buff, "Accept-Encoding: gzip,deflate\r\n");

    strcat((char *)buff, "\r\n");

}

안녕하세요
CLOSE WAIT 상태는 Peer로부터 FIN Packet을 수신한 상태입니다.
Peer에서 FIN Packet을 전송한 이유를 찾아야할것 같습니다.
추가로 CLOSE WAIT 상태에서도 데이터 송수신이가능합니다.
CLOSE WAIT 상태에서 close 명령어를 내리지않고 데이터 수신을 마저 한 후 에 close 되도록 하는것도 방법이 될 것 같습니다.

Copyright © 2017 WIZnet Co., Ltd. All Rights Reserved.