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.

[参考译文] TM4C129ENCPDT:如何在不打开新连接的情况下通过以太网从客户端向服务器发送数据/(同一套接字)

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1011870/tm4c129encpdt-how-to-send-data-from-client-to-server-over-ethernet-without-opening-new-connection-same-socket

器件型号:TM4C129ENCPDT

大家好、

我想通过以太网将792字节数据从客户端网关发送到服务器。 现在、我能够通过以太网发送所有数据、但每次打开新连接。 您可以看到黄色圆圈内的标记。  但是、我想在 不打开新连接的情况下通过以太网发送所有数据。 我的意思是 ı 只需要黄色圆圈中的一个连接。

您可以看到下面的代码。

如何将此代码配置为用于一个连接?  如果您有任何想法、请告诉我。

void ETH_Connection_Proccess(void)
{
    if(Gateway.ETHERNET_Mode == 0)
    {
        usb_printf("\n",1);
        usb_printf("ETH NOT ENABLED CAN'T POST MESSAGE\n", 35);
        Gateway.Priority = Gateway.ETHERNET_Priority + 1;
    }
    else if(ETH_Ctrl.eth_connection_status == 0)
    {
        usb_printf("\n",1);
        usb_printf("ETH NOT CONNECTED CAN'T POST MESSAGE\n", 37);
        Gateway.Priority = Gateway.ETHERNET_Priority + 1;
    }
    else if(ETH_Ctrl.eth_connection_status == 1 && Gateway.ETHERNET_Mode == 1)
    {
        ETH_Ctrl.connectTYPE = ETHERNET_POST;

        //
        //  Connect to host address
        //

        tcp_echoclient_connect(Gateway.Host_Address,Gateway.Remote_Port_Number);

        ETH_Ctrl.status = ETH_POST_CONNECT_SENT;
        ETH_Ctrl.timeout = 1;
    }
}

/**
 * @brief  Connects to the TCP echo server
 * @param  None
 * @retval None
 */
void tcp_echoclient_connect(char* IP_ARR,char* PORT_NUM)
{
    ip_addr_t DestIPaddr;

    uint16_t DestPORTAddr;

    /* create new tcp pcb */
    echoclient_pcb = tcp_new();

    if (echoclient_pcb != NULL)
    {
        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;
//    uint16_t index2;
    uint16_t data_lenght;
    data_lenght=792;
    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;

            if(ETH_Ctrl.connectTYPE == ETHERNET_POST)
            {
                // sprintf((char*)data,"%sContent-Length: %d\r\n\r\n%s\r\n",Gateway.POST_message_constant_part,Gateway.tcp_message_length,Gateway.tcp_message);
                 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

                if (es->p_tx)
                {
                    /* copy data to pbuf */
//                    pbuf_take(es->p_tx, (char*)data, strlen((char*)data));
                    pbuf_take(es->p_tx, (char*)data, data_lenght); //792 byte burada yukarıda yeni tanımlananan buffera, data bufferını kopyalıyoruz

                    /* pass newly allocated es structure as argument to tpcb */
                    tcp_arg(tpcb, es);

                    /* initialize LwIP tcp_recv callback function */
                    tcp_recv(tpcb, tcp_echoclient_recv);

                    /* initialize LwIP tcp_sent callback function */
                    tcp_sent(tpcb, tcp_echoclient_sent);

                    /* initialize LwIP tcp_poll callback function */
                    tcp_poll(tpcb, tcp_echoclient_poll, 1);

                    /* send data */
                    tcp_echoclient_send(tpcb,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;
}

谢谢你

BR、

Bekir

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

    您好!

     您如何知道连接已关闭? 您能通过 Wireshark 捕获进行确认吗? 您是否知道服务器或客户端是否关闭了连接? 在代码中,当 err != OK 或 es =NULL 时,您将关闭连接。 如果客户端因某些错误关闭连接、我建议您单步执行或在代码中放入断点。  

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

    您好、感谢您的回答。 我不使用 Wireshark。 我不确定哪一个连接关闭、但我想这取决于客户端。 因为我的设备是客户端。 我正在根据客户端对设备进行编程。 我使用调试来查看正在发生的情况。 为此 ,我检查(PCB/状态),它显示如下所示的状态。

    我在调试模式下检查(PCB->状态)的状态,发送 数据时显示 SYn_sent,在连接关闭时显示为已关闭。  

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

    您好!

     如果在此应用手册  https://www.ti.com/lit/pdf/spna248?中运行客户端示例、您是否会看到相同的连接问题

     我不确定您的代码来自哪里。 它与 STMicroelectronics 示例非常相似。 如果是这种情况、请阅读他们的许可协议  

    http://www.st.com/software_license_agreement_liberty_v2 并查看您是否符合条件4和2。 我不能支持您的意见。 我建议您联系 LwIP 论坛获取支持。  

    /**
      ******************************************************************************
      * @file    tcp_echoclient.c
      * @author  MCD Application Team
      * @version V1.1.0
      * @date    31-July-2013 
      * @brief   tcp echoclient application using LwIP RAW API
      ******************************************************************************
      * @attention
      *
      * <h2><center>Copyright COPYRIGHT 2013 STMicroelectronics</center></h2>
      *
      * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
      * You may not use this file except in compliance with the License.
      * You may obtain a copy of the License at:
      *
      *        www.st.com/software_license_agreement_liberty_v2
      *
      * Unless required by applicable law or agreed to in writing, software 
      * distributed under the License is distributed on an "AS IS" BASIS, 
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      * See the License for the specific language governing permissions and
      * limitations under the License.
      *
      ******************************************************************************
      */
    
    /* Includes ------------------------------------------------------------------*/
    #include "lwip/debug.h"
    #include "lwip/stats.h"
    #include "lwip/tcp.h"
    #include "main.h"
    #include "memp.h"
    #include "main.h"
    #include <stdio.h>
    #include <string.h>
    
    #if LWIP_TCP
    /* Private typedef -----------------------------------------------------------*/
    /* Private define ------------------------------------------------------------*/
    /* Private macro -------------------------------------------------------------*/
    /* Private variables ---------------------------------------------------------*/
    
    u8_t  recev_buf[50];
    __IO uint32_t message_count=0;
    
    u8_t   data[100];
    
    struct tcp_pcb *echoclient_pcb;
    
    
    /* ECHO protocol states */
    enum echoclient_states
    {
      ES_NOT_CONNECTED = 0,
      ES_CONNECTED,
      ES_RECEIVED,
      ES_CLOSING,
    };
    
    
    /* structure to be passed as argument to the tcp callbacks */
    struct echoclient
    {
      enum echoclient_states state; /* connection status */
      struct tcp_pcb *pcb;          /* pointer on the current tcp_pcb */
      struct pbuf *p_tx;            /* pointer on pbuf to be transmitted */
    };
    
    
    /* Private function prototypes -----------------------------------------------*/
    static err_t tcp_echoclient_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
    static void tcp_echoclient_connection_close(struct tcp_pcb *tpcb, struct echoclient * es);
    static err_t tcp_echoclient_poll(void *arg, struct tcp_pcb *tpcb);
    static err_t tcp_echoclient_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
    static void tcp_echoclient_send(struct tcp_pcb *tpcb, struct echoclient * es);
    static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err);
    
    /* Private functions ---------------------------------------------------------*/
    
    
    /**
    * @brief  Connects to the TCP echo server
    * @param  None
    * @retval None
    */
    void tcp_echoclient_connect(void)
    {
      struct ip_addr DestIPaddr;
      
      /* create new tcp pcb */
      echoclient_pcb = tcp_new();
      
      if (echoclient_pcb != NULL)
      {
        IP4_ADDR( &DestIPaddr, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3 );
        
        /* connect to destination address/port */
        tcp_connect(echoclient_pcb,&DestIPaddr,DEST_PORT,tcp_echoclient_connected);
      }
      else
      {
        /* deallocate the pcb */
        memp_free(MEMP_TCP_PCB, echoclient_pcb);
    #ifdef SERIAL_DEBUG
        printf("\n\r can not create tcp pcb");
    #endif 
      }
    }
    
    /**
      * @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;
          
          sprintf((char*)data, "sending tcp client message %d", message_count);
            
          /* allocate pbuf */
          es->p_tx = pbuf_alloc(PBUF_TRANSPORT, strlen((char*)data) , PBUF_POOL);
             
          if (es->p_tx)
          {       
            /* copy data to pbuf */
            pbuf_take(es->p_tx, (char*)data, strlen((char*)data));
            
            /* pass newly allocated es structure as argument to tpcb */
            tcp_arg(tpcb, es);
      
            /* initialize LwIP tcp_recv callback function */ 
            tcp_recv(tpcb, tcp_echoclient_recv);
      
            /* initialize LwIP tcp_sent callback function */
            tcp_sent(tpcb, tcp_echoclient_sent);
      
            /* initialize LwIP tcp_poll callback function */
            tcp_poll(tpcb, tcp_echoclient_poll, 1);
        
            /* send data */
            tcp_echoclient_send(tpcb,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;
    }

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

    您好!

    应用手册中没有相同的问题。 我不符合条件#2和#4。 我找到了一个可行的解决方案、但我不确定这是否正确。

    在开头、代码进入 eth_repeer_2状态。 它获得连接、然后再也不会进入该状态。 从 第一个状态获取 tpcbSa 套接字后、我将此套接字用于 tcp_EchoServer_send2 func 以连续发送数据。 您认为它是正确的。

    void ETH_Connection_Proccess(void)
    {
        if(Gateway.ETHERNET_Mode == 0)
        {
            usb_printf("\n",1);
            usb_printf("ETH NOT ENABLED CAN'T POST MESSAGE\n", 35);
            Gateway.Priority = Gateway.ETHERNET_Priority + 1;
        }
        else if(ETH_Ctrl.eth_connection_status == 0)
        {
            usb_printf("\n",1);
            usb_printf("ETH NOT CONNECTED CAN'T POST MESSAGE\n", 37);
            Gateway.Priority = Gateway.ETHERNET_Priority + 1;
        }
        else if(ETH_Ctrl.eth_connection_status == 1 && Gateway.ETHERNET_Mode == 1)
        {
            ETH_Ctrl.connectTYPE = ETHERNET_POST;
    
            //
            //  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_send2(tpcbSa, (unsigned char*)data, sizeof(data));
    
                if(ETH_Ctrl.connectTYPE == ETHERNET_POST)               //if post request and we want to close connection
                {
                    ETH_Ctrl.status = ETH_STATUS_POSTED;            //indicate that we post message successfully
                }
                else {
    
                    ETH_Ctrl.status = ETH_POST_CONNECT_SENT;
                    ETH_Ctrl.timeout = 1;
                }
            }
    }
    void tcp_echoserver_send2(struct tcp_pcb *tpcb, unsigned char *Source, unsigned int Size)
    {
        err_t wr_err = ERR_OK;
    
        /* enqueue data for transmission */
        wr_err = tcp_write(tpcb, Source, Size, 1);
    
        if(wr_err == ERR_OK)
            wr_err = tcp_output(tpcb);
    
    }

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

    您好!

     您没有 显示 ETH_Ctrl.eth_data_repeat 何时变为 ETH_repeer_2或 ETH_repeer_1以及 如何调用 ETH_Connection_Proccess ()。  我认为、如果 您确保只调用 一次 tcp_echoclient_connect、并且您已经证明它正常工作、那么我认为它应该是可以的。  

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

    Hİ μ A、

    很抱歉、我忘记了我的输入位置。  ETH_Ctrl.eth_data_repeat 在 tcp_client_connect 函数中变为 ETH_REPEACT_1。 因此、正如您所说、它将仅是一个连接。 之后、它只能运行  发送所有数据的 tcp_EchoServer_send2函数。 这种方式工作得非常好。 但是、假设服务器已关闭。 那么会发生什么情况? 我是否需要打开 新连接? 我是说我必须 将 ETH_Ctrl.eth_data_repeat 变为 能够进行新连接的 ETH_REPEACT_2吗?  

    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_2)
            {
                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);
            }
        }
    }

    谢谢你

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

    您好!

     我不确定您的问题的答案、因为我对此主题没有足够的了解。 我想客户端可能会 ping 服务器、如果您遇到超时、您就知道服务器关闭了连接。  

     下面的这篇文章可能会对您有所帮助。  您正在提出一个以网络为中心的问题、该问题超出了 MCU 的范围、我们有足够的知识来回答。 我建议您在 Google 上搜索一些关于如何处理服务器关闭连接的意见/想法。  

    https://www.geeksforgeeks.org/tcp-connection-termination/