linuxshowbye
linuxshowbye

Reputation: 1

While STM32 runs the LwIP protocol,How to implement 5 TCP connections?

Now,I am working with STM32F107+lwip.The aim is making a gateway which is used to exchange datas between ETHERNET and CAN. The UDP server is tested well.And now I want to increase the TCP server function,which can be permitted to establish 5 TCP connections.


My questions:
1 TCP connnection is tested ok,How to implement 5 TCP connections?


First,PC send data to STM32 by TCP connections. STM32 receives it and send it to CAN.Then,when STM32 receives datas from CAN ,it will send the datas to PC by all the TCP connections.Now,my idea is that typedef a structure,when STM32 received the data from PC,it will record the pcb,remote ip and remote port. And receiving data from CAN ,STM32 will send it through the recording data.The result is the data will be sent slowly when STM32 invokes the "tcp_write()" and "tcp_output"frequently.

So I wonder the solutions to implement multiple TCP connections.


#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++;
    }   
}

Upvotes: 0

Views: 2069

Answers (1)

Stian Skjelstad
Stian Skjelstad

Reputation: 2335

The tcp_server_accept() will contain the newly created connection. To this connection you can attach your context.

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;
}

Upvotes: 0

Related Questions