#include "tcp_server_demo.h"
#include "lwip/opt.h"
#include "lwip_comm.h"
#include "led.h"
#include "lwip/lwip_sys.h"
#include "lwip/api.h"
///
//本程序只供學習使用,未經作者許可,不得用于其它任何用途
//ALIENTEK STM32F407開發板
//NETCONN API編程方式的TCP服務器測試代碼
//正點原子@ALIENTEK
//創建日期:2014/8/15
//版本:V1.0
//版權所有,盜版必究。
//Copyright(C) 廣州市星翼電子科技有限公司 2009-2019
//All rights reserved
//*******************************************************************************
//修改信息
//無
//
u8 tcp_server_recvbuf[TCP_SERVER_RX_BUFSIZE]; //TCP客戶端接收數據緩沖區
u8 *tcp_server_sendbuf="Explorer STM32F407 NETCONN TCP Server send data\r\n";
u8 tcp_server_flag; //TCP服務器數據發送標志位
//TCP客戶端任務
#define TCPSERVER_PRIO 6
//任務堆棧大小
#define TCPSERVER_STK_SIZE 300
//任務堆棧
OS_STK TCPSERVER_TASK_STK[TCPSERVER_STK_SIZE];
//tcp服務器任務
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);
conn = netconn_new(NETCONN_TCP); //創建一個TCP鏈接
netconn_bind(conn,IP_ADDR_ANY,TCP_SERVER_PORT); //綁定端口 8號端口
netconn_listen(conn); //進入監聽模式
conn->recv_timeout = 10; //禁止阻塞線程 等待10ms
while (1)
{
err = netconn_accept(conn,&newconn); //接收連接請求
if(err==ERR_OK)newconn->recv_timeout = 10;
if (err == ERR_OK) //處理新連接的數據
{
struct netbuf *recvbuf;
netconn_getaddr(newconn,&ipaddr,&port,0); //獲取遠端IP地址和端口號
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); //發送tcp_server_sendbuf中的數據
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) //遍歷完整個pbuf鏈表
{
//判斷要拷貝到TCP_SERVER_RX_BUFSIZE中的數據是否大于TCP_SERVER_RX_BUFSIZE的剩余空間,如果大于
//的話就只拷貝TCP_SERVER_RX_BUFSIZE中剩余長度的數據,否則的話就拷貝所有的數據
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; //超出TCP客戶端接收數組,跳出
}
OS_EXIT_CRITICAL(); //開中斷
data_len=0; //復制完成后data_len要清零。
printf("%s\r\n",tcp_server_recvbuf); //通過串口發送接收到的數據
netbuf_delete(recvbuf);
}else if(recv_err == ERR_CLSD) //關閉連接
{
netconn_close(newconn);
netconn_delete(newconn);
printf("主機:%d.%d.%d.%d斷開與服務器的連接\r\n",remot_addr[0], remot_addr[1],remot_addr[2],remot_addr[3]);
break;
}
}
}
}
}
//創建TCP服務器線程
//返回值:0 TCP服務器創建成功
// 其他 TCP服務器創建失敗
INT8U tcp_server_init(void)
{
INT8U res;
OS_CPU_SR cpu_sr;
OS_ENTER_CRITICAL(); //關中斷
res = OSTaskCreate(tcp_server_thread,(void*)0,(OS_STK*)&TCPSERVER_TASK_STK[TCPSERVER_STK_SIZE-1],TCPSERVER_PRIO); //創建TCP服務器線程
OS_EXIT_CRITICAL(); //開中斷
return res;
}
以上是正點原子的代碼,正常開機可以聯網收發數據,拔掉網線再插上就連不上網,必須斷電重啟才可以。怎樣修改以上代碼,才能實現網線熱插拔自動重聯網? |