uip例程分析 web服务器stm32

uip例程分析

先看一下工作区里文件结构,如下

1.jpg

 

11.jpg

 

先看主程序

int main(void)

{   u8 tcp_server_tsta=0XFF;
    u8 ret = 0;
 u8 tcp_client_tsta=0XFF;

 BspInit();      //外设功能初始化
 
 
 
   while(SysTick_Config(72000));//系统滴答初始化72M
 
  if(tapdev_init()) //初始化ENC28J60错误
 {

           
    };

 InitNet();//网络初始化

 uip_listen(HTONS(1200));   //监听1200端口,用于TCP Server
 uip_listen(HTONS(80));    //监听80端口,用于Web Server
   tcp_client_reconnect();      //尝试连接到TCP Server端,用于TCP Client
 GPIO_ResetBits(GPIOA,GPIO_Pin_5);        
   while(1)
   {
 //  DebugOut(2, "\r\n uip polling!");
   uip_polling();//轮询查看数据是否接入
     
 
   }
  

}

 //uip事件处理函数
//必须将该函数插入用户主循环,循环调用.
void uip_polling(void)
{
  u8 i;
 static struct timer periodic_timer, arp_timer;
 static u8 timer_ok=0; 
 if(timer_ok==0)//仅初始化一次
 {
  timer_ok = 1;
  timer_set(&periodic_timer,CLOCK_SECOND/2);  //创建1个0.5秒的定时器
  timer_set(&arp_timer,CLOCK_SECOND*10);     //创建1个10秒的定时器 用来刷新
 }    
 uip_len=tapdev_read(); //从网络设备读取一个IP包,得到数据长度.uip_len在uip.c中定义
 if(uip_len>0)    //有数据
 {  
  //处理IP数据包(只有校验通过的IP包才会被接收)
  if(BUF->type == htons(UIP_ETHTYPE_IP))//是否是IP包?
  { 

   uip_arp_ipin(); //去除以太网头结构,更新ARP表
   uip_input();    //IP包处理
   //当上面的函数执行后,如果需要发送数据,则全局变量 uip_len > 0
   //需要发送的数据在uip_buf, 长度是uip_len  (这是2个全局变量)     
   if(uip_len>0)//需要回应数据
   {
    uip_arp_out();//加以太网头结构,在主动连接时可能要构造ARP请求
    tapdev_send();//发送数据到以太网  TCPclient 从此处发送
   }
  }else if (BUF->type==htons(UIP_ETHTYPE_ARP))//处理arp报文,是否是ARP请求包?
  {
 //     DebugOut(1, "\r\n uip ARP");
   uip_arp_arpin();
   
    //当上面的函数执行后,如果需要发送数据,则全局变量uip_len>0
   //需要发送的数据在uip_buf, 长度是uip_len(这是2个全局变量)
    if(uip_len>0)
   tapdev_send();//需要发送数据,则通过tapdev_send发送 
  }
 }else if(timer_expired(&periodic_timer)) //0.5秒定时器超时
 {
//     DebugOut(2, "\r\n 0.5秒时间到");
  timer_reset(&periodic_timer);  //复位0.5秒定时器
  //轮流处理每个TCP连接, UIP_CONNS缺省是40个 
  for(i=0;i<UIP_CONNS;i++)
  {
   uip_periodic(i); //处理TCP通信事件 
    //当上面的函数执行后,如果需要发送数据,则全局变量uip_len>0
   //需要发送的数据在uip_buf, 长度是uip_len (这是2个全局变量)
    if(uip_len>0)
   {
    uip_arp_out();//加以太网头结构,在主动连接时可能要构造ARP请求
    tapdev_send();//发送数据到以太网
   }
  }
#if UIP_UDP //UIP_UDP
  //轮流处理每个UDP连接, UIP_UDP_CONNS缺省是10个
  for(i=0;i<UIP_UDP_CONNS;i++)
  {
   uip_udp_periodic(i); //处理UDP通信事件
    //当上面的函数执行后,如果需要发送数据,则全局变量uip_len>0
   //需要发送的数据在uip_buf, 长度是uip_len (这是2个全局变量)
   if(uip_len > 0)
   {
    uip_arp_out();//加以太网头结构,在主动连接时可能要构造ARP请求
    tapdev_send();//发送数据到以太网
   }
  }
#endif
  //每隔10秒调用1次ARP定时器函数 用于定期ARP处理,ARP表10秒更新一次,旧的条目会被抛弃
  if(timer_expired(&arp_timer))
  {
  //   DebugOut(1, "\r\n uip  timer_expired!");
   timer_reset(&arp_timer);
   uip_arp_timer();
  }
 }
}

//TCP应用接口函数(UIP_APPCALL)
//完成TCP服务(包括server和client)和HTTP服务
void tcp_demo_appcall(void)

   
 switch(uip_conn->lport)//本地监听端口80和1200
 {
  case HTONS(80):
     httpd_appcall(); //http协议默认使用80端口
   break;
  case HTONS(1200):
      tcp_server_demo_appcall();

   break;
  default:       
      break;
 }     
 switch(uip_conn->rport) //远程连接1400端口
 {
     case HTONS(1400):
   tcp_client_demo_appcall();
        break;
     default:
        break;
 }  
}

http处理

//http服务(WEB)处理
void httpd_appcall(void)
{
 struct httpd_state *s = (struct httpd_state *)&(uip_conn->appstate);//读取连接状态
 if(uip_closed() || uip_aborted() || uip_timedout())//异常处理
 {
 }else if(uip_connected())//连接成功
 {
  PSOCK_INIT(&s->sin, s->inputbuf, sizeof(s->inputbuf) - 1);
  PSOCK_INIT(&s->sout, s->inputbuf, sizeof(s->inputbuf) - 1);
  PT_INIT(&s->outputpt);
  s->state = STATE_WAITING;
  /*    timer_set(&s->timer, CLOCK_SECOND * 100);*/
  s->timer = 0;
  
  handle_connection(s);//处理
 }else if(s!=NULL)
 {
  if(uip_poll())
  {
   ++s->timer;
   if(s->timer >= 20)uip_abort();
    else s->timer = 0;
  }
  handle_connection(s);
 }else uip_abort();// 
}

 进入handle_connection(s)

//分析http数据
static void handle_connection(struct httpd_state *s)
{
handle_input(s);  //处理http输入数据
 if(s->state==STATE_OUTPUT)
 handle_output(s);//输出状态,处理输出数据
}

进入handle_input(s);

//处理HTTP输入数据
static PT_THREAD(handle_input(struct httpd_state *s))

里边包含调用此函数

{

 strncpy(s->filename, http_index_html, sizeof(s->filename));//更新页面

}

http_index_html[]数组包含要显示的页面数组。

web服务器设计代码解析到此为止!

sitemap