LWIP_STM32_ENC28J60_NETCONN_TCP_CLIENT(4)

    既然udp說完了,那接下來天然就是TCP通信了,今天說說TCP客戶端通信,也就是單片機做爲客戶端,主機PC做爲服務器數組

    相比於udp而言,tcp增長了一個鏈接服務器的流程,首先仍是建立tcp_client任務服務器

    

//建立TCP客戶端線程
//返回值:0 TCP客戶端建立成功
//        其餘 TCP客戶端建立失敗
INT8U tcp_client_init(void)
{
    INT8U res;
    OS_CPU_SR cpu_sr;
    
    OS_ENTER_CRITICAL();    //關中斷
    res = OSTaskCreate(tcp_client_thread,(void*)0,(OS_STK*)&TCPCLIENT_TASK_STK[TCPCLIENT_STK_SIZE-1],TCPCLIENT_PRIO); //建立TCP客戶端線程
    OS_EXIT_CRITICAL();        //開中斷
    
    return res;
}

任務的執行流程以下tcp

//tcp客戶端任務函數
static void tcp_client_thread(void *arg)
{
    OS_CPU_SR cpu_sr;
    u32 data_len = 0;
    struct pbuf *q;
    err_t err,recv_err;
    static ip_addr_t server_ipaddr,loca_ipaddr;
    static u16_t          server_port,loca_port;

    LWIP_UNUSED_ARG(arg);
    server_port = REMOTE_PORT;
    IP4_ADDR(&server_ipaddr, 192,168, 1,105);
    
    while(dhcpstatus != 2)//等待dhcp成功
    {
        OSTimeDly(10);
        //printf("wait dhcp\r\n");
    }
    
    while (1) 
    {
        tcp_clientconn = netconn_new(NETCONN_TCP);  //建立一個TCP連接
        err = netconn_connect(tcp_clientconn,&server_ipaddr,server_port);//鏈接服務器
        if(err != ERR_OK)  netconn_delete(tcp_clientconn); //返回值不等於ERR_OK,刪除tcp_clientconn鏈接
        else if (err == ERR_OK)    //處理新鏈接的數據
        { 
            struct netbuf *recvbuf;
            tcp_clientconn->recv_timeout = 10;
            netconn_getaddr(tcp_clientconn,&loca_ipaddr,&loca_port,1); //獲取本地IP主機IP地址和端口號
            printf("鏈接上服務器%d.%d.%d.%d,本機端口號爲:%d\r\n",192,168, 1,105,loca_port);
            while(1)
            {
                if(keyValue == KEY_LEFT)
                {
                    tcp_client_flag = LWIP_SEND_DATA;
                    keyValue = 0;
                }
                if((tcp_client_flag & LWIP_SEND_DATA) == LWIP_SEND_DATA) //有數據要發送
                {
                    err = netconn_write(tcp_clientconn ,tcp_client_sendbuf,strlen((char*)tcp_client_sendbuf),NETCONN_COPY); //發送tcp_server_sentbuf中的數據
                    if(err != ERR_OK)
                    {
                        printf("發送失敗\r\n");
                    }
                    tcp_client_flag &= ~LWIP_SEND_DATA;
                }
                    
                if((recv_err = netconn_recv(tcp_clientconn,&recvbuf)) == ERR_OK)  //接收到數據
                {    
                    OS_ENTER_CRITICAL(); //關中斷
                    memset(tcp_client_recvbuf,0,TCP_CLIENT_RX_BUFSIZE);  //數據接收緩衝區清零
                    for(q=recvbuf->p;q!=NULL;q=q->next)  //遍歷完整個pbuf鏈表
                    {
                        //判斷要拷貝到TCP_CLIENT_RX_BUFSIZE中的數據是否大於TCP_CLIENT_RX_BUFSIZE的剩餘空間,若是大於
                        //的話就只拷貝TCP_CLIENT_RX_BUFSIZE中剩餘長度的數據,不然的話就拷貝全部的數據
                        if(q->len > (TCP_CLIENT_RX_BUFSIZE-data_len)) memcpy(tcp_client_recvbuf+data_len,q->payload,(TCP_CLIENT_RX_BUFSIZE-data_len));//拷貝數據
                        else memcpy(tcp_client_recvbuf+data_len,q->payload,q->len);
                        data_len += q->len;      
                        if(data_len > TCP_CLIENT_RX_BUFSIZE) break; //超出TCP客戶端接收數組,跳出    
                    }
                    OS_EXIT_CRITICAL();  //開中斷
                    data_len=0;  //複製完成後data_len要清零。                    
                    printf("%s\r\n",tcp_client_recvbuf);
                    netbuf_delete(recvbuf);
                }else if(recv_err == ERR_CLSD)  //關閉鏈接
                {
                    netconn_close(tcp_clientconn);
                    netconn_delete(tcp_clientconn);
                    printf("服務器%d.%d.%d.%d斷開鏈接\r\n",192,168, 1,105);
                    break;
                }
            }
        }
        OSTimeDly(10);
    }
}

裏面核心的就是netconn的使用,這個熟能生巧函數

忘了傳代碼,補上spa

http://download.csdn.net/detail/dengrengong/8599071
相關文章
相關標籤/搜索