This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TM4C1294NCPDT:以太网连接在发送数据的2/3小时后中断

Guru**** 2553260 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1017939/tm4c1294ncpdt-ethernet-connection-break-down-after-2-3-hours-sending-data

器件型号:TM4C1294NCPDT

大家好、

我一直在尝试从设备/网关通过以太网向 TCP 服务器发送数据。  与服务器和设备建立一次连接后、我将在没有关闭连接的情况下发送数据。 我在 tcp_echoclient_connected 中获得了套接字信息、如 ES2和 tpcbSa。 获取套接字信息后、我在 tcp_EchoServer_send3函数中使用此信息。 因此、我能够每5秒发送一次所有数据。 但在经过2/3小时 后、WR_ERR 返回 ERR_MEM。 然后停止发送数据。 我想通过以太网发送数据、而不 是每5秒停止一次。  我想在返回 ERR_MEM 后、我使用 tcp_write 函数发送请求。 但它没有解决。

所以、

-为什么  wr_err 在2/3小时后返回 ERR_MEM? 如何避免这种情况?

-返回 ERR_MEM 后、应执行什么操作来返回 ERR_OK 或继续发送数据?

您对解决此问题有什么想法或建议吗?

谢谢你  

BR  

Bekir

        //
        //  Connect to host address
        //
        if(ETH_Ctrl.eth_data_repeat == ETH_REPEAT_2 )
        {
            tcp_echoclient_connect(Gateway.Host_Address,Gateway.Remote_Port_Number);
        }
        else if(ETH_Ctrl.eth_data_repeat == ETH_REPEAT_1)
        {
            memcpy(data,Gateway.tcp_message,Gateway.tcp_message_length);

            tcp_echoserver_send3(tpcbSa, (unsigned char*)data, sizeof(data), es2);
        }

void tcp_echoclient_connect(char* IP_ARR,char* PORT_NUM)
{
    {
        /* create new tcp pcb */
        echoclient_pcb = tcp_new();
        if (echoclient_pcb != NULL)
        {
            ETH_Ctrl.eth_data_repeat = ETH_REPEAT_1;
            ipaddr_aton((const char *)IP_ARR,&DestIPaddr);
            DestPORTAddr = atoi(PORT_NUM);

            /* connect to destination address/port */
            tcp_connect(echoclient_pcb,&DestIPaddr,DestPORTAddr,tcp_echoclient_connected);
        }
    }
}


/**
 * @brief Function called when TCP connection established
 * @param tpcb: pointer on the connection contol block
 * @param err: when connection correctly established err should be ERR_OK
 * @retval err_t: returned error
 */
static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
    struct echoclient *es = NULL;

    if (err == ERR_OK)
    {
        /* allocate structure es to maintain tcp connection informations */
        es = (struct echoclient *)mem_malloc(sizeof(struct echoclient));

        if (es != NULL)
        {
            es->state = ES_CONNECTED;
            es->pcb = tpcb;

            tpcbSa = tpcb;
            if(ETH_Ctrl.connectTYPE == ETHERNET_POST)
            {
                 memcpy(data,Gateway.tcp_message,Gateway.tcp_message_length); //1024 tcp message datanın ilk 792 adet datası databuffer içine kaydedilir

                /* allocate pbuf */
                es->p_tx = pbuf_alloc(PBUF_TRANSPORT, sizeof(data) , PBUF_POOL); //burası gönderilen buffer ile aynı ozellikte bos bir buffer yaratıyor
                es2=es;

                return ERR_OK;
                
            }
        }
        else
        {
            {
                /* close connection */
                tcp_echoclient_connection_close(tpcb, es);

                /* return memory allocation error */
                return ERR_MEM;
            }
        }
    }
    else
    {
        /* close connection */
        tcp_echoclient_connection_close(tpcb, es);
    }
    return err;
}

void tcp_echoserver_send3(struct tcp_pcb *tpcb, unsigned char *Source, unsigned int Size, struct echoclient * es)
{
    err_t wr_err = ERR_OK;

    /* enqueue data for transmission */
    wr_err = tcp_write(tpcb, Source, Size, 1); //TCP_WRITE_FLAG_COPY

    if(wr_err == ERR_OK)
    {
        if(es->p_tx != NULL)
        {
             /* increment reference count for es->p */
             pbuf_ref(es->p_tx);
        }
    }

    else
    {
        if(wr_err == ERR_MEM)
        {
            tcp_write(tpcb, Source, Size, 1);

            if (sizeof(data) > tcp_sndbuf(tpcb))
            {
               usb_printf("Not enough memory. Could not send data buffer\n", 50);
            }
        }
       else
        {

        }
    }
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    按相反顺序:

    1) 1)如果从 tcp_write 获取 ERR_MEM、则不适合立即再次调用 tcp_write、因为(很可能)它会再次失败。 相反,请保存您正在执行的操作,然后在 tcp_sent()或 tcp_poly()回调函数中重试。

    2) 2)当系统正常运行时,ERR_MEM 是一种流控制形式,这意味着您发送数据的速度太快,因此应暂停,直到 TCP 堆栈让您知道可以继续(请参阅上面的(1))。

    3) 3)如果 ERR_MEM 持续存在、这意味着您丢失("泄露")缓冲区、大概是 pbufs、即您正在分配但不释放缓冲区。 pbuf_ref ()作为可能导致泄漏的东西脱颖而出、因为我看不到匹配的 pbuf_free。 您能解释一下该 pbuf_ref 调用的用途吗?