Experiment of establishing communication between TCP Server and host based on LWIP

LWIP version: 2.0.3

The last article is to write how to port LWIP to the board, and record the network communication with the host based on LWIP tonight.

First, I opened the experimental routine of the atom, and browsed it for a while, and felt that the TCP network network communication is just such a routine. What to create, configure, bind, monitor, accept...., decisively copy the source file to the project path, adjust the header file to include until the compilation is correct. Add tcp_server_init( ) to the main, download the test, and sure enough there is a problem. Ping can't work, embarrassing.....

Problem solving process:

It's a good thing that something goes wrong, and you can learn more about LWIP (forcibly comfort yourself). Then add printf output to find the source of the problem, and finally trace it to the netconn_alloc function in netconn_new. The solution is as follows:

I thought that the function memp_malloc called internally failed to apply for memory. Enter the function and start reading the source code. It is found that the MEMP_MEM_MALLOC macro has not been opened. It is misunderstood that the memory will not be successfully applied for if the macro is not enabled. Later, the test found that it is not the problem. The official comment is as follows:

/**
 * MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator.
 * Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution
 * speed (heap alloc can be much slower than pool alloc) and usage from interrupts
 * (especially if your netif driver allocates PBUF_POOL pbufs for received frames
 * from interrupt)!
 * ATTENTION: Currently, this uses the heap for ALL pools (also for private pools,
 * not only for internal pools defined in memp_std.h)!
 */

If this macro is not enabled, the LWIP kernel will directly fetch the corresponding structure from the lwip pool. The memory of the pool has been applied for before the LWIP kernel runs. The official recommendation is not to enable this macro, because speed (heap alloc can be much slower than pool alloc ).

Later, I continued to search for the problem and found a fatal problem: the mailbox creation function sys_mbox_new called in the netconn_alloc function did not allocate memory for its parameter (a mailbox pointer). This is a residual problem during transplantation, and finally found it. This problem is solved by the mem_malloc/mem_free functions provided in the LWIP kernel as follows:

err_t sys_mbox_new( sys_mbox_t *mbox, int size)
{
    *mbox = mem_malloc(sizeof(TQ_DESCR));
    .....
}

void sys_mbox_free(sys_mbox_t * mbox)
{
    .......
    mem_free(*mbox);
    *mbox=NULL;
}

Recompile the project, download it to the board, it works perfectly!

operation result:

Open the network assistant, configure the tcp server and port, click connect, the display is as follows:

The serial port assistant is displayed as follows:

Attachment: lwip_server.c source code

#include "tcp_server.h"
#include "lwip/opt.h"
#include "lwip_app.h"
#include "lwip/sys.h"
#include "lwip/api.h"
#include "delay.h"
#include "string.h"  
 
u8 tcp_server_recvbuf[TCP_SERVER_RX_BUFSIZE];   
static const u8 tcp_server_sendbuf[] = "Welcome to connect to the LWIP server.\r\n";    
u8 tcp_server_flag = 0xff;                                                  
#define TCPSERVER_PRIO      6
#define TCPSERVER_STK_SIZE  300
OS_STK TCPSERVER_TASK_STK[TCPSERVER_STK_SIZE];

static void tcp_server_thread(void *arg)
{
    OS_CPU_SR cpu_sr;
    u32 data_len = 0;
    struct pbuf *q;
    err_t err,recv_err;
    u8 remot_addr[4];
    struct netconn *conn, *newconn;
    static ip_addr_t ipaddr;
    static u16_t            port;
    
    LWIP_UNUSED_ARG(arg);

    /* 创建 TCP、绑定、监听 */
    conn = netconn_new(NETCONN_TCP);                
    netconn_bind(conn,IP_ADDR_ANY,TCP_SERVER_PORT);
    netconn_listen(conn);   
    
    /* 禁止阻塞线程,等待时间为 10ms */
    conn->recv_timeout = 10;                    
    
    while (1) 
    {
        err = netconn_accept(conn,&newconn);  
        if(err==ERR_OK) newconn->recv_timeout = 10;
        
        if (err == ERR_OK)    
        { 
            struct netbuf *recvbuf;

            /* 获取到客户端的 IP 及端口号 */
            netconn_getaddr(newconn,&ipaddr,&port,0); 
            
            remot_addr[3] = (uint8_t)(ipaddr.addr >> 24); 
            remot_addr[2] = (uint8_t)(ipaddr.addr >> 16);
            remot_addr[1] = (uint8_t)(ipaddr.addr >> 8);
            remot_addr[0] = (uint8_t)(ipaddr.addr);
            printf("主机:%d.%d.%d.%d 连接上服务器,主机端口号为:%d\r\n",remot_addr[0], remot_addr[1],remot_addr[2],remot_addr[3],port);
            
            while(1)
            {
                if((tcp_server_flag & LWIP_SEND_DATA) == LWIP_SEND_DATA)        
                {
                    /* 各客户端发送消息 */
                    err = netconn_write(newconn ,tcp_server_sendbuf,strlen((char*)tcp_server_sendbuf),NETCONN_COPY); 
                    if(err != ERR_OK)
                    {
                        printf("发送失败\r\n");
                    }
                    tcp_server_flag &= ~LWIP_SEND_DATA;
                }
                
                /* 接收消息 */
                if((recv_err = netconn_recv(newconn,&recvbuf)) == ERR_OK)  
                {       
                    OS_ENTER_CRITICAL();        
                    memset(tcp_server_recvbuf,0,TCP_SERVER_RX_BUFSIZE);         
                    
                    /* 将缓冲区信息转存到自定义空间 */       
                    for(q=recvbuf->p;q!=NULL;q=q->next)                                 
                    {
                        if(q->len > (TCP_SERVER_RX_BUFSIZE-data_len)) memcpy(tcp_server_recvbuf+data_len,q->payload,(TCP_SERVER_RX_BUFSIZE-data_len));
                        else memcpy(tcp_server_recvbuf+data_len,q->payload,q->len);
                        data_len += q->len;     
                        if(data_len > TCP_SERVER_RX_BUFSIZE) break; 
                    }
                    OS_EXIT_CRITICAL();                                     
                    data_len=0;                     
                    printf("%s\r\n",tcp_server_recvbuf);  
                    netbuf_delete(recvbuf);
                    
                /* 断开连接 */
                }else if(recv_err == ERR_CLSD)              
                {
                    netconn_close(newconn);
                    netconn_delete(newconn);
                    tcp_server_flag = 0xff; 
                    printf("主机:%d.%d.%d.%d 断开与服务器的连接\r\n",remot_addr[0], remot_addr[1],remot_addr[2],remot_addr[3]);
                    break;
                }
            }
        }
        delay_ms(10);
    }
}


INT8U tcp_server_init(void)
{
    INT8U res=0;
    OS_CPU_SR cpu_sr;

    OS_ENTER_CRITICAL();    
    
    /* 创建 TCP 服务器任务 */
    res = OSTaskCreate(tcp_server_thread,(void*)0,(OS_STK*)&TCPSERVER_TASK_STK[TCPSERVER_STK_SIZE-1],TCPSERVER_PRIO); 
    OS_EXIT_CRITICAL();     
    
    return res;
}

This article refers to the LWIP network experiment from Atom, thanks

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325692331&siteId=291194637