最新在使用LWIP + MQTT的应用过程中,出现一个很奇怪的问题,当上位机反送的JSON长度过大时,我的stm32收到的数据就会有问题:
上图中成功接收到失败接收口相关1个字节,用wireshark看数据包长度分别是591和590:
发现可能是我的接收BUFF不够大引起的,程序中有MqttRxBuff大小定义为1024,改成2048还是一样接收失败:
看来问题不是在这个BUFF,
接着看MQtt对应的TCP接收BUFF,在LWIP的opt.h中看到有如下一些定义,从图中看到PBUF_POOL_BUFSIZE大小取决到TCP_MESS大小。当前TCP_MESS大小于536 对应计算出的PBUF_POOL_BUFSIZE为592,刚好与我们之前的591相近,看到就是这个问题我们把
按理把这个参数改大后应该可以解决,但是发现实际发现还是不行!
仿真发现数据从路由器发送到MCU时,就已经分成了两包,最终将TCP的接收函数改写成如下问题解决。
/**
* @brief tcp_receiv callback
* @param arg: argument to be passed to receive callback
* @param tpcb: tcp connection control block
* @param err: receive error code
* @retval err_t: retuned error
*/
err_t MqttTcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
struct mqttclinet *es;
err_t ret_err;
int i = 0;
LWIP_ASSERT("arg != NULL",arg != NULL);
es = (struct mqttclinet *)arg;
/* if we receive an empty tcp frame from server => close connection */
if (p == NULL)
{
/* remote host closed connection */
es->state = ES_CLOSING;
if(es->p_tx == NULL)
{
/* we're done sending, close connection */
MqttTcp_connection_close(tpcb, es);
}
else
{
/* send remaining data*/
MqttTcp_send(tpcb, es);
}
ret_err = ERR_OK;
}
/* else : a non empty frame was received from echo server but for some reason err != ERR_OK */
else if(err != ERR_OK)
{
/* free received pbuf*/
pbuf_free(p);
ret_err = err;
}
else if(es->state == ES_CONNECTED)
{
/* Acknowledge data reception */
tcp_recved(tpcb, p->tot_len);
#if 0
// 回显功能
es->p_tx = p;
MqttTcp_send(tpcb, es);
#else
// 将要接收的数据放到BUFF里
if( p->flags == 0 ) // 如果出现了分包的,在这里时行判断
{
MqttRxOffset = p->len;
memcpy((void *)MqttRxTemp,p->payload,p->len);
}
else
{
if( MqttRxOffset )
{
if( (MqttRxBwp + MqttRxOffset) - MqttRxBrp < MQTTBUFFSIZE )
{
for( i=0; i<MqttRxOffset; i++ )
{
MqttRxBuff[MqttRxBwp] = MqttRxTemp[i];
MqttRxBwp = (MqttRxBwp+1)%MQTTBUFFSIZE;
}
}
MqttRxOffset = 0;
}
if( (MqttRxBwp + p->tot_len) - MqttRxBrp < MQTTBUFFSIZE )
{
for( i=0; i<p->tot_len; i++)
{
MqttRxBuff[MqttRxBwp] = *((uint8_t *)(p->payload)+i);
MqttRxBwp = (MqttRxBwp+1)%MQTTBUFFSIZE;
}
}
}
pbuf_free(p);
#endif
ret_err = ERR_OK;
}
/* data received when connection already closed */
else
{
/* Acknowledge data reception */
tcp_recved(tpcb, p->tot_len);
/* free pbuf and do nothing */
pbuf_free(p);
ret_err = ERR_OK;
}
return ret_err;
}