STM32 + W5500 + Http client
STM32 + W5500 + Http client
0
Project description
下??求的header信息,包括以下????信息:
1、?求方式+接口名?+??和??版本(GET /file/FLASH_OPER.bin_1.1.3 HTTP/1.1rn)
2、文件服?器主机IP+端口 (?例:192.168.1.105:8888rn)
3、?接??(Connection: Keep-Alivern)
4、?求端名?(User-Agent: W5500rn)
5、?求端接收的??(Accept-Encoding: gzip,deflatern)
6、?求??束??(rn)
以上是?求的分析,文件服?器返回的信息如下:
?文件服?器返回?的?据分析,?文和文件?容不是一次性??的,是流的方式多次??的。
返回的?文,包含以下????点:
1、返回的???(HTTP/1.1 200rn)
2、接收范? 字?流(Accept-Ranges: bytesrn)
3、?容?度(Content-Length: 3904rn)
4、??束??(rn)
5、字?流Data?度和Content-Length是相等的。
以上是基于??器下?文件的?程分析的,那?STM32 W5500下?文件的?程,模???器下?文件,?理?上??也是???的。
HTTP??是在TCP的基?上封?的??,W5500的TCP Client端?服?端???接的?程在此不描述。
STM32 W5500下?文件有???点:
1、解析文件服?器返回的?文,判?返回?是否?200,只有200才代表成功;判?是否?字?流;解析出文件的大小(?度)
2、文件字?流和返回?文的分割,以及?存??的?据反?搬?(?竟W5500 一次最多可以收2Kbytes 的?据)。
3、判?文件下?是否完成的依据。
STM32 W5500?求和接收的?程:
??送一次?求?文后,不?接收文件服?器返回的信息,?果是要?接收到文件字?流和 Content-Length的相等,文件下?成功,要?各?原因失?(?接超?,?取超?,返回?不正?,不是字?流等)。
好像??的都?了,下面?出STM32 W5500 Http GET方式下?文件的代?(我??下? 4k/13k/67k 左右的文件都可以),例程中打印了 各?分支的log信息,?文件下?的?容通?串口DMA的方式打印出?。(工程可以看我的 基?配置文章下?,再???主??函?替?)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
void log_net(char *log);
-
-
void func_pack_http_get_download_header(u8* buff, u16 size_buff, u8* srv_ip, u16 srv_port, char* interface);
-
u8 func_http_get_download_file(u8 sockno, u8* srv_ip, u16 srv_port, char* interface, u16 timeout_ms, u8* buff, u16 size_buff);
-
u8 func_analysis_http_download_header(u8* buffer, u16 len_buf, u8 *resp_code, u8 *is_stream, u32 *cont_len);
-
-
u8 buf[2048];
-
int main(void)
-
{
-
-
u8 mac[6]={0, };
-
DHCP_Get dhcp_get;
-
-
//FIXME input your server ip to download file
-
u8 srv_ip[] = {192, 168, 1, 105};
-
u16 srv_port = 8888;
-
-
-
systick_configuration();
-
init_led();
-
init_hardware_usart2_dma(115200);
-
-
init_system_spi();
-
func_w5500_reset();
-
-
getMacByLockCode(mac);
-
setSHAR(mac);
-
-
sysinit(txsize, rxsize);
-
setRTR(2000);
-
setRCR(3);
-
-
//USART DMA problem: 2 bytes missing
-
func_usart2_dma_send_bytes(mac, 2);
-
delay_ms(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(0, srv_ip, srv_port, "/file/FLASH_OPER.bin_1.1.3", 5000, buf, sizeof(buf));
-
-
for(;;)
-
{
-
func_led1_toggle();
-
delay_ms(500);
-
}
-
}
-
-
u8 func_http_get_download_file(u8 sockno, u8* srv_ip, u16 srv_port, char* interface, u16 timeout_ms, u8* buff, u16 size_buff)
-
{
-
u16 local_port = 60000, len = 0, cnt = 0;
-
u8 sendok = 0, recv_start = 0;
-
-
u8 cache[2048];
-
u16 cache_cont_len;
-
u32 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)
-
{
-
u8 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
-
{
-
u32 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
-
{
-
u32 tmp_len;
-
u8* pos_header;
-
pos_header = (u8*)strstr((char*)cache, "rnrn");
-
//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
-
{
-
u32 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
-
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;
-
download_cont_len = sizeof(cache) + cache_cont_len;
-
-
}
-
}
-
-
if(download_cont_len == cont_len)// small file download done
-
{
-
log_net("7");
-
func_usart2_dma_send_bytes(cache, cache_cont_len);
-
//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
-
{
-
u32 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
-
}
-
delay_ms(1);
-
}
-
}
-
-
u8 func_analysis_http_download_header(u8* buffer, u16 len_buf, u8 *resp_code, u8 *is_stream, u32 *cont_len)
-
{
-
*resp_code = 0;
-
*is_stream = 0;
-
*cont_len = 0;
-
if(strstr((char*)buffer, "rnrn") != 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, "rn");
-
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)
-
{
-
u8 logsrv_ip[] = {192, 168, 1, 105};
-
socket(2, Sn_MR_UDP, 7890, 0x00);
-
sendto(2, (u8*)log, strlen(log), logsrv_ip, 9876);
-
}
-
-
void func_pack_http_get_download_header(u8* buff, u16 size_buff, u8* srv_ip, u16 srv_port, char* interface)
-
{
-
u8 tmp[64];
-
memset(buff, 0, size_buff);
-
//header
-
memcpy(buff, "GET ", strlen("GET "));
-
strcat((char *)buff, interface);
-
strcat((char *)buff, " HTTP/1.1rn");
-
memset(tmp, 0 , sizeof(tmp));
-
sprintf((char*)tmp, "Host: %d.%d.%d.%d:%drn", srv_ip[0], srv_ip[1], srv_ip[2], srv_ip[3], srv_port);
-
strcat((char *)buff, (char*)tmp);
-
strcat((char *)buff, "Connection: Keep-Alivern");
-
strcat((char *)buff, "User-Agent: W5500rn");
-
strcat((char *)buff, "Accept-Encoding: gzip,deflatern");
-
strcat((char *)buff, "rn");
-
}
最后,附上我??的效果?:
串口打印的字??和 Content-Length的?度一致,?和原bin文件做了?比,?容一致。