20130408-[转]uIP的移植及对TCP/IP协议的理解(1)待续

来源:互联网 发布:apache配置怎么快 编辑:程序博客网 时间:2024/05/17 05:55

原文地址:http://blog.sina.com.cn/s/blog_9007cf3801015de2.html

 

uIP主流程:

while(1)
        {
            uip_len = tapdev_read(uip_buf);
            if(uip_len > 0)
            {
              //收到的是IP数据,调用uip_input()处理
              if(BUF->type == htons(UIP_ETHTYPE_IP))
              {
                      uip_arp_ipin();//ARP地址检验
                      uip_input();
                     
                //处理完成后,如果uip_buf中有数据,则调用etherdev_send发送出去
                      if(uip_len > 0)
                {
                        uip_arp_out();//以太网帧头封装
                        tapdev_send(uip_buf,uip_len);
                      }
              }
              //收到的是ARP数据,调用uip_arp_arpin()处理
              else if(BUF->type == htons(UIP_ETHTYPE_ARP))
              {
                uip_arp_arpin();
                     
                      if(uip_len > 0)
                      {
                        tapdev_send(uip_buf,uip_len);
                      }
              }
            }
            //查看0.5S是否到了,到了则调用uip_periodic处理TCP超时程序
            else if(timer_expired(&periodic_timer))
            {
              timer_reset(&periodic_timer);
              for(i = 0; i < UIP_CONNS; i++)
              {
                uip_periodic(i);
               
                if(uip_len > 0)
                {
                  uip_arp_out();
                  tapdev_send(uip_buf,uip_len);
                }
              }
        #if UIP_UDP
              for(i = 0; i < UIP_UDP_CONNS; i++) {
                uip_udp_periodic(i);
               
                if(uip_len > 0) {
                  uip_arp_out();
                  tapdev_send(uip_buf,uip_len);
                }
              }
        #endif
             
              if(timer_expired(&arp_timer))
              {
                timer_reset(&arp_timer);
                uip_arp_timer();
              }
            }
          }

一般这个循环是不需要修改的,我暂时还没有碰到。现在试用了一下UDP,TCP,WEB,都不需要修改这个循环。

一些初始化函数:

    uip_init();

 // init MAC address
 uip_ethaddr.addr[0] = EMAC_ADDR0;
 uip_ethaddr.addr[1] = EMAC_ADDR1;
 uip_ethaddr.addr[2] = EMAC_ADDR2;
 uip_ethaddr.addr[3] = EMAC_ADDR3;
 uip_ethaddr.addr[4] = EMAC_ADDR4;
 uip_ethaddr.addr[5] = EMAC_ADDR5;
 uip_setethaddr(uip_ethaddr);//设定以太网MAC地址

 uip_ipaddr(ipaddr, 192,168,0,100);
 uip_sethostaddr(ipaddr);//设置主机IP地址

 uip_ipaddr(ipaddr, 192,168,0,1);
 uip_setdraddr(ipaddr);//设定的是默认路由器地址

 uip_ipaddr(ipaddr, 255,255,255,0);
 uip_setnetmask(ipaddr);//设定子网掩码

 

接下来就要针对UDP或者是TCP做一些监听或连接:

针对UDP:

        uip_ipaddr(ripaddr,192,168,0,101);//PC机IP地址
        uip_udp_conn = uip_udp_new(&ripaddr,HTONS(1000));//建立远端端口1000,端口是以网络字节数学的,所以要用到HTONS
        if( uip_udp_conn != NULL){
           uip_udp_bind(uip_udp_conn,HTONS(3022));//绑定本地端口3022
        }

针对TCP:

       uip_listen(HTONS(23));//监听端口23

下面来看下网络调试助手,刚开始使用的时候,也是费了我好大尽的。

《原创》uIP的移植及对TCP/IP协议的理解(1)待续
右上角的框是配置一些UDP的信息,分别是协议选择,本地IP地址以及本地端口号。一般在电脑中,端口号是随机配置的,当然也可以在助手中直接配置,方便在代码中调试。等connect成功之后,右下角红色框会出现远程IP地址及端口号的配置。如果是PC机和单片机相连,那么右下角就是单片机的一些信息。

 

至于TCP协议,一般都是TCP Server配置IP地址,端口号信息。服务器的端口号要与单片机中监听端口号相一致。


写下来说说这个协议栈的最最重要的函数,uip_process(u8_t flag)。TCP,UDP都用到这个函数。如果没什么特殊的要求,这个函数是不需要做任何修改的。按照报文,进行分析,没什么错误的话,最终都会调用到一个函数,UIP_APPCALL()。这个函数是需要用户自己编写的。有个宏,

#define UIP_UDP_APPCALL  udp_appcall (UDP的用户接口函数)//适用于UDP

#define UIP_APPCALL     tcp_appcall//适用于TCP


void udp_appcall( void )
{
   if(uip_udp_conn->rport == HTONS(1000))
   {
     if(uip_poll())//如果是轮询的话
     {
       myudp_send("hello\n",6);
     }
     if(uip_newdata())//如果有新数据的话
     {
       newdata();
     }
   }
}

void tcp_appcall( void )
{
     if(uip_newdata())
     {
       newdata();
     }
}

上面是我编的两个调用函数。


void
uip_send(const void *data, int len)
{
  if(len > 0) {
    uip_slen = len;
    if(data != uip_sappdata) {
      memcpy(uip_sappdata, (data), uip_slen);
    }
  }
}

void myudp_send(char *str,short n)
{
   char  *nptr;
   nptr = (char*)uip_appdata;
   memcpy(nptr,str,n);
   uip_udp_send(n);//发送n个数据
}


void newdata()
{
    char   *nptr;
    short   len;
    len = uip_datalen();//读取数据长度
    nptr = (char*)uip_appdata;//取得数据起始指针
    if(len<4)
        myudp_send("Please check the command!\n",26);
    else  if(strncmp(nptr,"getname",7)== 0)
      myudp_send("My name is xiaoxu.",19);
    else 
     // uip_send("Unkown command!\n",16);
      myudp_send("Unkown command!\n",16);
}

这些也是我借鉴网上前辈的经验。uip_send这个函数,主要是发送应用层的数据,其他的会在其他函数中慢慢封装。

这个差不多就是整个uIP重要函数及要自己添加的函数。

原创粉丝点击