Closed chengshuihang closed 2 years ago
您好,您截图的这段代码使用方法是正确的。以下问题麻烦您再确认一下以便分析:
抱歉,我写错了,是nx_web_http_client_response_body_get返回的NX_NOT_CONNECTED(0x38),原因应该是数据包没有发送出去,因此nx_web_http_client_response_body_get函数无法获取到响应,奇怪的是nx_web_http_client_post_start_extended和nx_web_http_client_put_packet返回的都是NX_SUCCESS。
上面给了两份截图,一份是在status为NX_NOT_CONNECTED时,count次数为3的截图,另外一份是采集post请求数据的截图。
可以看到,post请求了3次,但是采集到的post请求只有2次。当然截图无法证明NX_NOT_CONNECTED是由nx_web_http_client_response_body_get返回的,这个需要再次复现这个现象(它并不好复现,我会继续测试的)。
那么当前就是两个问题了,1 为什么会发送失败 2 post请求头数据会不一样。
这是测试代码
您好,截图中确实无法定位error status是哪个函数返回的。您在测试的时候可以加一些调试信息,如在返回error status的时候输出: http_client.nx_web_http_client_state web_client_pool.nx_packet_pool_available 等信息。
另外您能否将数据包文件分享给我,我可以看一下TCP的连接情况,以及HTTP包里具体的数据。 谢谢。
是的截图无法定位,我给一份可以定位的截图
我发现这个问题只会出现在单步调试时,我在全速运行时,并没有发现这个故障。在单步调试时,故障在偶数次会稳定出现,全速运行,并未出现。我将本次单步调试的数据包也发送给您。
web_http_post_err.zip
您好,数据包里可以看出是server端主动断开了连接,您可以确认一下server端配置的超时时间吗?
默认的30s,server断开链接的话,nx_web_http_client_post_start_extended和nx_web_http_client_put_packet返回NX_SUCCESS是正常的吗?
从server回复的response里可以看到keep-alive timeout设置为5s,数据包里server也是5s后发了fin包断开了连接,符合预期。
如果server已经断开连接之后,post_start和put_packet应该是会失败的,数据包里也确实没有抓到第二次post request。您可以先尝试把server端的keep-alive timeout时间调长一些再测试一下。另外再确认一下您的工程有没有开优化。谢谢。
您好,您说的应该是对的,应该就是keep-alive导致的数据无法发出,比较难的是我的测试软件中没有keep-alive参数配置功能。另外我的工程没有开优化。post_start和put_packet确实是返回的NX_SUCCESS,这个在调试截图中就能确认。
您好,根据现在函数返回成功却没有抓到数据包的情况,可能是post_start和put_packet虽然返回的NX_SUCCESS,但是底层并没有发送成功。您可以在程序运行到第二次循环时,在_nx_ip_packet_send()函数里加一个断点,单步调试观察一下后续有没有出错。另外您的代码里有一处需要调整一下,在status为NX_SUCCESS的时候不需要release http_post_packet.
好的,我会进行尝试。 在status为NX_SUCCESS的时候不需要release http_post_packet吗?
这是put_packet的代码,只有在非NX_SUCCESS put_packet才能释放packet,若status为NX_SUCCESS,不进行release的话,不就内存泄漏了吗?
您好,根据您的方案,我在下面截图打了断点,获取到了USB端的返回值,其返回了0。这么看来问题出在我的USB设备上,我会接下来排查我的USB设备,非常感谢您的帮助! 另外关于release packet,你能确认下吗?
您好,status为NX_SUCCESS时,将由netx内部来release这个packet。status为error时,由用户来release。您圈出来的部分我们内部代码有点问题,不应该在5942行调用nx_packet_release,我们会在下一个版本修复这个问题。谢谢。
`UINT _nx_web_http_client_put_packet(NX_WEB_HTTP_CLIENT client_ptr, NX_PACKET packet_ptr, ULONG wait_option) {
NX_PACKET response_packet_ptr; CHAR buffer_ptr; UINT length; UINT status;
/* First, check and see if the client instance is still in the PUT state. */
if (client_ptr -> nx_web_http_client_state != NX_WEB_HTTP_CLIENT_STATE_PUT &&
client_ptr -> nx_web_http_client_state != NX_WEB_HTTP_CLIENT_STATE_POST)
{
/* Client not ready, return error. */
return(NX_WEB_HTTP_NOT_READY);
}
/* Next, check and see if there is a response from the Server. */
status = _nx_web_http_client_receive(client_ptr, &response_packet_ptr, NX_NO_WAIT);
/* Check for an early response from the Server. */
if (status == NX_SUCCESS)
{
/* This is an error condition since the Server should not respond until the PUT is complete. */
/* Setup pointer to server response. */
buffer_ptr = (CHAR *) response_packet_ptr -> nx_packet_prepend_ptr;
/* Determine if it is an authentication error. */
if (((buffer_ptr + 11) < (CHAR *)response_packet_ptr -> nx_packet_append_ptr) &&
(buffer_ptr[9] == '4') && (buffer_ptr[10] == '0') && (buffer_ptr[11] == '1'))
{
/* Inform caller of an authentication error. */
status = NX_WEB_HTTP_AUTHENTICATION_ERROR;
}
else
{
/* Inform caller of general Server failure. */
status = NX_WEB_HTTP_INCOMPLETE_PUT_ERROR;
}
/* Release the packet. */
nx_packet_release(response_packet_ptr);
/* Disconnect and unbind the socket. */
_nx_web_http_client_error_exit(client_ptr, wait_option);
/* Return to the READY state. */
client_ptr -> nx_web_http_client_state = NX_WEB_HTTP_CLIENT_STATE_READY;
/* Return error to caller. */
return(status);
}
/* Otherwise, determine if the packet length fits in the available bytes to send. */
if (packet_ptr -> nx_packet_length >
(client_ptr -> nx_web_http_client_total_transfer_bytes - client_ptr -> nx_web_http_client_actual_bytes_transferred))
{
/* Request doesn't fit into the remaining transfer window. */
return(NX_WEB_HTTP_BAD_PACKET_LENGTH);
}
/* Remember the packet length. */
length = packet_ptr -> nx_packet_length;
/* Now send the packet out. */
status = _nx_web_http_client_send(client_ptr, packet_ptr, wait_option);
/* Determine if the send was successful. */
if (status != NX_SUCCESS)
{
/* No, send was not successful. */
/* Release the packet. */
nx_packet_release(packet_ptr);
/* Disconnect and unbind the socket. */
_nx_web_http_client_error_exit(client_ptr, wait_option);
/* Return to the READY state. */
client_ptr -> nx_web_http_client_state = NX_WEB_HTTP_CLIENT_STATE_READY;
/* Return an error. */
return(status);
}
/* Otherwise, update the actual bytes transferred. */
client_ptr -> nx_web_http_client_actual_bytes_transferred = client_ptr -> nx_web_http_client_actual_bytes_transferred + length;
/* Return status to caller. */
return(NX_SUCCESS);
}` 那是不是意味着,我只需要在status为 NX_WEB_HTTP_NOT_READY、NX_WEB_HTTP_AUTHENTICATION_ERROR、NX_WEB_HTTP_INCOMPLETE_PUT_ERROR、NX_WEB_HTTP_BAD_PACKET_LENGTH的时候,进行release就行?
是的,针对当前的版本,您可以在这些error_status时进行release。
好的,非常感谢!
您好,关于nx_web_http_client_request_packet_allocate成功后数据包release问题。在http内部有些错误会release,有些不会release,在nx_web_http_client_request_packet_allocate函数的调用方,依据nx_packet_data_append和nx_web_http_client_put_packet的返回值来判断是否需要release,比较麻烦。有没有一种办法,可以检测到allocate的数据当前可以release?
Hi @chengshuihang 谢谢你的反馈,是的,我们也注意到了这个问题,会在下一个release里面修复这个问题。现在能否把5948行的packet release移掉试试?
/* Now send the packet out. */
status = _nx_web_http_client_send(client_ptr, packet_ptr, wait_option);
/* Determine if the send was successful. */
if (status != NX_SUCCESS)
{
/* No, send was not successful. */
/* Release the packet. */
//nx_packet_release(packet_ptr);
/* Disconnect and unbind the socket. */
_nx_web_http_client_error_exit(client_ptr, wait_option);
/* Return to the READY state. */
client_ptr -> nx_web_http_client_state = NX_WEB_HTTP_CLIENT_STATE_READY;
/* Return an error. */
return(status);
}
好的!
您好!关于web http post内存池的问题,我需要传输0-15K大小的数据,一次post请求,我的http内存池该如何分配?下面代码是我现在使用的方案,它有一些问题,在传输12K的数据时,尾部有一些数据并没有发出来。当我将CLIENT_POOL_SIZE增大到(CLIENT_PACKET_SIZE * 12),它是可以发送出来的,但是这样我的内存消耗太大了。我没有找到发生这个现象的原因,您那边知道吗? `
static uint8_t nx_client_pool[CLIENT_POOL_SIZE]; static NX_PACKET_POOL web_client_pool; static uint8_t nx_packet_pool[NX_PACKET_POOL_SIZE]; static NX_PACKET_POOL nx_pool; status = nx_packet_pool_create(&nx_pool, "Nx Pool", PACKET_PAYLOAD_SIZE, nx_packet_pool, NX_PACKET_POOL_SIZE); status = nx_packet_pool_create(&web_client_pool, "HTTP Client Packet Pool", CLIENT_PACKET_SIZE, nx_client_pool, CLIENT_POOL_SIZE); static UINT RealTimeUploadDataUpload(NXD_ADDRESS server_ip_addr, UINT server_port) { TboxRealTimePackage_t package; UINT status = NX_SUCCESS; NX_PACKET http_get_packet = NULL; NX_PACKET http_post_packet = NULL; uint8_t* buffer = NULL; uint32_t size = 0u; uint32_t item;
/* 取出一帧待发送的数据 */
status = tx_queue_receive(&real_time_placing_order_send_queue, (void*)&item, TX_NO_WAIT);
if(status == TX_SUCCESS){
/* 转换为数据包格式 */
package = (TboxRealTimePackage_t*)item;
/* 有无网? */
if(mqtt_connect_flag == false){
/* 无网,直接通知发送失败 */
package->res(package, false);
}
else{
/* 获取数据包 */
buffer = package->buffer;
/* 获取数据包大小 */
size = package->size;
/* 启动http post请求 */
status = nx_web_http_client_realtime_data_upload_post_start_extended(&http_client,
server_ip_addr, server_port,
HTTP_URL_REAL_TIME_DATA,
strlen(HTTP_URL_REAL_TIME_DATA),
size, NX_WAIT_FOREVER);
if(status == NX_SUCCESS){
/* 申请http数据包 */
status = nx_web_http_client_request_packet_allocate(&http_client, &http_post_packet, NX_WAIT_FOREVER);
if(status == NX_SUCCESS){
/* 将当前数据包,添加到http数据包中 */
status = nx_packet_data_append(http_post_packet, buffer, size, &web_client_pool, NX_WAIT_FOREVER);
if(status == NX_SUCCESS){
/* 将http数据包发送出去 */
status = nx_web_http_client_put_packet(&http_client, http_post_packet, NX_WAIT_FOREVER);
if(status == NX_SUCCESS){
/* 获取服务器响应 */
status = nx_web_http_client_response_body_get(&http_client, &http_get_packet, NX_WAIT_FOREVER);
/* 成功从服务器获取到响应数据包? */
if(http_get_packet != NULL){
/* 释放服务器响应数据包 */
nx_packet_release(http_get_packet);
/* 清零,防止野指针 */
http_get_packet = NULL;
/* 通知发送成功 */
package->res(package, true);
/* 返回结果状态 */
return status;
}
}
else{
/* 释放这个http发送数据包 */
nx_packet_release(http_post_packet);
/* 清空,防止野指针 */
http_post_packet = NULL;
}
}
else{
/* 释放这个http发送数据包 */
nx_packet_release(http_post_packet);
/* 清空,防止野指针 */
http_post_packet = NULL;
}
}
}
/* 通知发送失败 */
package->res(package, false);
}
}
return status;
}
`
这是将CLIENT_POOL_SIZE增大到(CLIENT_PACKET_SIZE 12)后的过程
这是CLIENT_POOL_SIZE为(CLIENT_PACKET_SIZE 9)的过程
对比发现,最后有几包数据包,并没有发出来。
post_一次成功一次失败.zip
你可以尝试将nx_pool传给web http client, 这样你只需要一个packet pool.
非常感谢!按照您说的方案,我现在传输20K数据都是正常的。
好的,那我先把这个issue关了,有问题可以随时提问。
好的
您好,请问有关于web http client post的例程吗?我在使用nx_web_http_client_put_packet出现了一些问题,想对照确认下。问题是nx_web_http_client_put_packet在某些时候会返回NX_NOT_CLOSED。当前测试代码如下:![image](https://user-images.githubusercontent.com/45716763/167985073-11f90bb4-9f9c-4fce-86de-bf4dd7b7c090.png)