---
title: "STM32 + W5500 + Http client"
url: "https://maker.wiznet.io/tonywang_/projects/STM32-W5500-Http-client/"
markdown_url: "https://maker.wiznet.io/tonywang_/projects/STM32-W5500-Http-client/md"
type: "UCC: User Created Content"
author: "tonywang_"
author_url: "https://maker.wiznet.io/tonywang_/"
original_author: "tonywang_"
original_url: "https://blog.csdn.net/lnniyunlong99/article/details/105559284?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165391438916781483746346%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=165391438916781483746346&bi"
published: "2022-07-05"
language: "en"
likes: 0
views: 769
comments: 0
source: "WIZnet Makers (https://maker.wiznet.io/)"
---

# STM32 + W5500 + Http client

> STM32 + W5500 + Http client

Original author: tonywang_ (source: https://blog.csdn.net/lnniyunlong99/article/details/105559284?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165391438916781483746346%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=165391438916781483746346&bi)

## Article

??天在做STM32 W5500通?HTTP GET?求的方式下?bin文件，以??OTA在?升?，到?上?了一圈，????有?多有效的信息和?料。于是我就??了一下，把思路和???程分享出?。 ??W5500文件下?的??前提： 1、STM32 W5500的基?配置，使得 ??端的CMD命令?口能?PING通W5500，《STM32F103RC??W5500入?，?可ping通》。 2、STM32 W5500的TCP Client收??据???有??，《STM32F1 W5500 TCP Client 回???》。 3、一?可用的文件服?器，文件的URL地址放到??器的地址?后，可以正常下?文件。 4、?HTTP??有基本的??。 文件的URL地址放到??器的地址?后，通?Wireshark工具，先看看文件下?的?程，都?生可一些什? 下??求的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的方式打印出?。（工程可以看我的 基?配置文章下?，再???主??函?替?） #ifndef __STM32F10X_H #define __STM32F10X_H #include "stm32f10x.h" #endif #ifndef __Z_UTIL_TIME_H #define __Z_UTIL_TIME_H #include "z_util_time.h" #endif #ifndef __Z_HARDWARE_LED_H #define __Z_HARDWARE_LED_H #include "z_hardware_led.h" #endif #ifndef __Z_HARDWARE_SPI_H #define __Z_HARDWARE_SPI_H #include "z_hardware_spi.h" #endif #ifndef __W5500_H #define __W5500_H #include "w5500.h" #endif #ifndef __SOCKET_H #define __SOCKET_H #include "socket.h" #endif #ifndef __W5500_CONF_H #define __W5500_CONF_H #include "w5500_conf.h" #endif #ifndef __DHCP_H #define __DHCP_H #include "dhcp.h" #endif #ifndef __Z_HARDWARE_USART2_H #define __Z_HARDWARE_USART2_H #include "z_hardware_usart2.h" #endif #include &lt;stdlib.h> 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 &lt;= 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 &lt;= 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 &lt;= 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文件做了?比，?容一致。

---

Source: https://maker.wiznet.io/tonywang_/projects/STM32-W5500-Http-client/
