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