既然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