Пока STM32 работает по протоколу LwIP , Как реализовать 5 TCP-соединений?

Сейчас я работаю с STM32F107 + lwip. Целью является создание шлюза, который будет использоваться для обмена данными между ETHERNET и CAN. UDP-сервер хорошо протестирован, и теперь я хочу усилить функцию TCP-сервера, которому можно разрешить установить 5 TCP-соединений.


Мои вопросы:
1 TCP-соединение протестировано нормально. Как реализовать 5 TCP-соединений?


Во-первых, ПК отправляет данные в STM32 через TCP-соединения. STM32 получает его и отправляет в CAN. Затем, когда STM32 получает данные от CAN, он отправляет данные на ПК по всем TCP-соединениям. Теперь я считаю, что typedef структуры , когда STM32 получил данные с ПК, он запишет плату, удаленный IP и удаленный порт. И, получив данные от CAN, STM32 отправит их через данные записи. В результате данные будут отправляться медленно, когда STM32 часто вызывает «tcp_write ()» и «tcp_output».

Так что мне интересно, какие решения для реализации нескольких TCP-соединений.


#define TCP_WORKING       0xaa
#define TCP_FREE         0xa5
typedef struct Cmd_TCPData
{
        unsigned char               TCP_STATUS;
        unsigned char               cmd_flag;
        unsigned short              remote_port;
        unsigned short              data_len;
        struct ip_addr              remote_ip;
        unsigned char               *pData;
        struct tcp_pcb              *TCP_pcb;
}Cmd_TCPData;
Cmd_TCPData cmd_tcp;
Cmd_TCPData tcp_list[5];
static u8 TcpListNum;
void TCP_server_init(void)
{
    struct tcp_pcb *pcb;
    err_t err;
    /*****************************************************/
    pcb = tcp_new();                                
    if (!pcb)
    {
        return ;
    }
    err = tcp_bind(pcb,IP_ADDR_ANY,devInfo.udpPort);        
    if(err != ERR_OK)
    {
        return ;
    }
    pcb = tcp_listen(pcb);                          
    tcp_accept(pcb,tcp_server_accept);             
}

static err_t tcp_server_accept(void *arg,struct tcp_pcb *pcb,err_t err)
{
    tcp_setprio(pcb, TCP_PRIO_MIN);         
    tcp_recv(pcb,tcp_server_recv);              
    err = ERR_OK;
    return err;
}

static err_t tcp_server_recv(void *arg, struct tcp_pcb *pcb,struct pbuf *p,err_t err)
{

    struct pbuf *p_temp = p;
    int nPos=0; 
    u8 searchtemp=0;                  
    //TCP_pcbA=pcb;

    while(tcp_list[searchtemp].TCP_STATUS==TCP_WORKING)               
    {
        if(tcp_list[searchtemp].remote_ip.addr!= pcb->remote_ip.addr)  
        {
            searchtemp++;                      
        }                                                            
        else                                                        
            break;
        if(searchtemp==5)                                          
        {                                                          
            searchtemp=0;
            break;
        }
    }
        /******copy*******************/
    tcp_list[searchtemp].TCP_pcb=pcb;
    tcp_list[searchtemp].pData = TCPRecvBuf;
    tcp_list[searchtemp].remote_port=pcb->remote_port;
    tcp_list[searchtemp].remote_ip = pcb->remote_ip;
    tcp_setprio(tcp_list[searchtemp].TCP_pcb, TCP_PRIO_MIN+searchtemp);         
    if(p_temp != NULL)
    {   
        tcp_recved(pcb, p_temp->tot_len);                                       
        while(p_temp != NULL)   
        {               

        //  tcp_write(pcb,p_temp->payload,p_temp->len,TCP_WRITE_FLAG_COPY);        
        //  tcp_output(pcb);
            memcpy(tcp_list[searchtemp].pData+nPos,p_temp->payload,p_temp->len);
            nPos += p_temp->len;
            p_temp = p_temp->next;
        }       
    }
    else
    {
        tcp_close(pcb);                                         
    }
    tcp_list[searchtemp].data_len = nPos;
    flash_led_tcp = 1;
    tcp_list[searchtemp].TCP_STATUS= TCP_WORKING;
    TcpListNum=searchtemp;
    pbuf_free(p);   
    err = ERR_OK;
    return err;
}

void send_tcp_data(u8_t *pPtr,u16_t data_len)                            
{
    u8 x=0;
    while(x<5)
    {
        if(tcp_list[x].TCP_STATUS==TCP_WORKING)                      
        {
            //TCP_pcbA->remote_port=tcp_list[x].remote_port;
            //TCP_pcbA->remote_ip= tcp_list[x].remote_ip;
            tcp_write(tcp_list[x].TCP_pcb,pPtr,data_len,TCP_WRITE_FLAG_COPY);        
            tcp_output(tcp_list[x].TCP_pcb);                        
        }
        OSTimeDlyHMSM(0, 0, 0, 250);//250ms     
        x++;
    }   
}

person linuxshowbye    schedule 29.06.2017    source источник
comment
Трудно понять ваш код, если в нем нет описательных комментариев. Почему вы не используете netconn?   -  person Jeroen3    schedule 03.07.2017


Ответы (1)


Tcp_server_accept () будет содержать вновь созданное соединение. К этой связи вы можете прикрепить свой контекст.

struct myclient_t
{
    struct tcp_pcb *pcb;
    /* all the variables uniqe for tracking this specific connection.. parser-state, receive/send buffers, statistics... */
    int foo;
    int bar;
};

static err_t tcp_server_accept(void *arg,struct tcp_pcb *pcb,err_t err)
{
    err_t ret_err;
    struct struct myclient_t *context = 0;
    int i;

    context = new_client();
    if (!context )
    {
        return ERR_MEM;
    }

    context->pcb = pcb;

    /* pass newly allocated es structure as argument to newpcb */
    tcp_arg(newpcb, context); /* recv, sent, error and poll callbacks will have context their argument, which is uniqe for each connection */

    /* initialize lwip tcp_recv callback function for newpcb  */ 
    tcp_recv(newpcb, tcp_server_recv

    tcp_sent(newpcb, tcp_server_sent);

    /* initialize lwip tcp_err callback function for newpcb  */
    tcp_err(newpcb, tcp_server_error);

    /* initialize lwip tcp_poll callback function for newpcb */
    tcp_poll(newpcb, tcp_server_poll, 1);

    return ERR_OK;
}
person Stian Skjelstad    schedule 14.05.2018