之前用webclient-master时候遇到过内存泄漏,现在整理工程改成固定版本webclient-v2.1.0,感觉还是有泄漏现象,官方代码库更新一下把Bug去掉吧!
2019.07月份的笔记
——————————————————————————————————
貌似存在内存泄漏
msh />free
total memory: 56464
used memory : 27472
maximum allocated memory: 30840
msh />web_post_file_test
[D/web] host address: 192.168.137.1 , port: 880
[D/web] request header:
[D/web] GET /web_upload/ HTTP/1.1
[D/web] Host: 192.168.137.1
[D/web] User-Agent: RT-Thread HTTP Agent
msh />free
total memory: 56464
used memory : 31580
maximum allocated memory: 49408
msh />web_post_file_test
[D/web] host address: 192.168.137.1 , port: 880
[D/web] request header:
[D/web] GET /web_upload/ HTTP/1.1
[D/web] Host: 192.168.137.1
[D/web] User-Agent: RT-Thread HTTP Agent
msh />free
total memory: 56464
used memory : 35688
maximum allocated memory: 53516
msh />web_post_file_test
[D/web] host address: 192.168.137.1 , port: 880
[D/web] request header:
[D/web] GET /web_upload/ HTTP/1.1
[D/web] Host: 192.168.137.1
[D/web] User-Agent: RT-Thread HTTP Agent
[E/at.skt] no memory for esp8266 device(esp0) URC receive buffer(2920).
msh />
首先是发现 webclient_post_file 中在初始化 session->header
时没有处理 session->header->length
//int webclient_post_file(const char* URI, const char* filename, const char* form_data)
session->header->buffer = web_strdup(header);//附近没有session->header->length有关的代码
之后发现 session->header->buffer = web_strdup(header);
语句貌似很危险
尝试按web_post_test
调用的webclient_post_comm
的方式初始化header
解决了之前怀疑的内存泄漏的问题
接下来比较Fiddler向MVC发的File抓包,发现“Content-Length:”
是在“boundary”
里面的,遂改之
/**
* post file to http server.
*
* @param URI input server address
* @param filename post data filename
* @param form_data form data
*
* @return <0: POST request failed
* =0: success
*/
#define webclient_post_file_backup (0)
int webclient_post_file(const char* URI, const char* filename,
const char* form_data)
{
size_t length;
char boundary[60];
int fd = -1, rc = WEBCLIENT_OK;
unsigned char *buffer = RT_NULL, *buffer_ptr;
struct webclient_session* session = RT_NULL;
fd = open(filename, O_RDONLY, 0);
if (fd < 0)
{
LOG_D("post file failed, open file(%s) error.", filename);
rc = -WEBCLIENT_FILE_ERROR;
goto __exit;
}
/* get the size of file */
length = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
buffer = (unsigned char *) web_malloc(WEBCLIENT_RESPONSE_BUFSZ);
if (buffer == RT_NULL)
{
LOG_D("post file failed, no memory for response buffer.");
rc = -WEBCLIENT_NOMEM;
goto __exit;
}
#if webclient_post_file_backup
char *header = RT_NULL;
header = (char *) web_malloc(WEBCLIENT_HEADER_BUFSZ);
if (header == RT_NULL)
{
LOG_D("post file failed, no memory for header buffer.");
rc = -WEBCLIENT_NOMEM;
goto __exit;
}
rt_memset(header,0,WEBCLIENT_HEADER_BUFSZ);
#endif
/* build boundary */
rt_snprintf(boundary, sizeof(boundary), "----------------------------%012d", rt_tick_get());
/* build encapsulated mime_multipart information*/
buffer_ptr = buffer;
/* first boundary */
buffer_ptr += rt_snprintf((char*) buffer_ptr,
WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer), "--%s <br>", boundary);
buffer_ptr += rt_snprintf((char*) buffer_ptr,
WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
"Content-Disposition: form-data; %s <br>", form_data);
buffer_ptr += rt_snprintf((char*) buffer_ptr,
WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
//"Content-Type: application/octet-stream<br>");
"Content-Type: image/jpeg<br>");
/* calculate content-length */
length += buffer_ptr - buffer;
length += rt_strlen(boundary) + 6; /* add the last boundary */
#if webclient_post_file_backup
/* build header for upload */
char *header_ptr;
header_ptr = header;
header_ptr += rt_snprintf(header_ptr,
WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
"Content-Length: %d <br>", length);
header_ptr += rt_snprintf(header_ptr,
WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
"Content-Type: multipart/form-data; boundary=%s <br>", boundary);
session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
if(session == RT_NULL)
{
rc = -WEBCLIENT_NOMEM;
goto __exit;
}
session->header->buffer = web_strdup(header);
//session->header->length = (size_t)(-1);
#else
/* build header for upload */
session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
if(session == RT_NULL)
{
rc = -WEBCLIENT_NOMEM;
goto __exit;
}
//session->header->buffer = web_strdup(header);
//调整"Content-Length:"到boundary内部
webclient_header_fields_add(session, "Content-Type: multipart/form-data; boundary=%s <br>", boundary);
webclient_header_fields_add(session, "Content-Length: %d <br>", length);
#endif
rc = webclient_post(session, URI, NULL);
rt_thread_mdelay(100);
if( rc< 0)
{
goto __exit;
}
/* send mime_multipart */
webclient_write(session, buffer, buffer_ptr - buffer);
rt_thread_mdelay(100);
/* send file data */
while (1)
{
length = read(fd, buffer, WEBCLIENT_RESPONSE_BUFSZ);
if (length <= 0)
{
break;
}
webclient_write(session, buffer, length);
rt_thread_mdelay(100);
}
/* send last boundary */
rt_snprintf((char*) buffer, WEBCLIENT_RESPONSE_BUFSZ, " <br>--%s-- <br>", boundary);
webclient_write(session, buffer, rt_strlen(boundary) + 6);
__exit:
if (fd >= 0)
{
close(fd);
}
if (session != RT_NULL)
{
webclient_close(session);
}
if (buffer != RT_NULL)
{
web_free(buffer);
}
#if webclient_post_file_backup
if (header != RT_NULL)
{
web_free(header);
}
#endif
return 0;
}