uip协议栈移植到window

uip移植到window平台目的是为仿真单片机运行环境,方便调试和学习,加快开发。

一、准备工作

下载uip 1.0  https://github.com/adamdunkels/uip/tags

下载wpcap sdk

下载wireshark

 

二、uip协议栈移植

     使用vs2008创建控制台工程,解压uip代码。复制unix文件夹,重命名为win。

  2.1、修改clock-arc.c

clock_time_t
clock_time(void)
{
 return GetTickCount();
}

以上函数是获取系统运行时间,单位为ms。

2.2、修改tapdev.c

//网卡初始化

void tapdev_init(void)
{
   EthernetInit();
}

//读取网络数据

unsigned int tapdev_read(void)
{
 return EthernetRead(uip_buf,UIP_BUFSIZE);
}

//发送网络数据

void tapdev_send(void)
{
 EthernetSend(uip_buf,uip_len);
}

 

2.3、增加intetypes.h

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;


#define IP2DWORD(a,b,c,d)    ((uint32_t)(uint8_t)(d)|(uint32_t)(uint8_t)(c)<<8|(uint32_t)(uint8_t)(b)<<16|(uint32_t)(uint8_t)(a)<<24)
#define DWORD2IP(val,array)   \
 do {       \
  array[0] = (uint8_t)((val >> 24) & 0x000000FF); \
  array[1] = (uint8_t)((val >> 16) & 0x000000FF); \
  array[2] = (uint8_t)((val >> 8) & 0x000000FF); \
  array[3] = (uint8_t)((val >> 0) & 0x000000FF); \
 } while(0)

#define ENDIANCHANGE32(A)                 ((((uint32_t)(A) & 0xff000000) >> 24) | \
        (((uint32_t)(A) & 0x00ff0000) >> 8) | \
        (((uint32_t)(A) & 0x0000ff00) << 8) | \
        (((uint32_t)(A) & 0x000000ff) << 24))

#define snprintf _snprintf

2.4、配置uip-conf.h

#define UIP_CONF_BUFFER_SIZE     640   //wifi环境下DHCP包大于420

#define UIP_UDP_APPCALL uip_udp_appcall

typedef struct httpd_state uip_tcp_appstate_t;
typedef struct httpd_state uip_udp_appstate_t;

至此已移植完成。

三、收发网络数据包

使用uip协议栈后,要直接收发以太网包。这时要用到winpcap。

int EthernetInit()
{

if (pcap_findalldevs(&alldevs, errbuf) == -1)
 {
  return -2;
 }

 

} if ((fp = pcap_open_live(alldevs->name,  
        65536,   // portion of the packet to capture. It doesn't matter in this case 
        1,    // promiscuous mode (nonzero means promiscuous)
        1000,   

        errbuf   // error buffer
        )) == NULL)
 {
  DisplayErrorMsg(errbuf);
  pcap_freealldevs(alldevs);
  alldevs = NULL;
  return -1;
 }

 

int EthernetSend(void* buffer,int nSize)
{
 if(fp == NULL) return -1;

 if (pcap_sendpacket(fp,(const u_char*)buffer,nSize) != 0)
 {
   pcap_geterr(fp);
  return 0;
 }

 return 1;
}

 

int EthernetRead(char* buffer,int nSize)
{
 if(fp == NULL) return -1;
pcap_loop(fp, 1, packet_handler, NULL);

}

void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{

memcpy(szCapBuffer,pkt_data,bufferLen);

}

 

四、测试

void uIP_Net_Init(void)
{
  timer_set(&periodic_timer, CLOCK_SECOND / 2);
  timer_set(&arp_timer, CLOCK_SECOND * 10);
 

  uip_ethaddr.addr[0] = 0x00;
  uip_ethaddr.addr[1] = 0x1B;
  uip_ethaddr.addr[2] = 0x11;
  uip_ethaddr.addr[3] = 0x13;
  uip_ethaddr.addr[4] = 0x86;
  uip_ethaddr.addr[5] = 0xb0;

  tapdev_init();
  uip_init();
  dhcpc_init(&uip_ethaddr,6);
  dhcpc_request();

}


int UipPro(void)
{
  int i;
  if(1)
  {
   uip_len = tapdev_read();
   if(uip_len > 0)
   {
    if(BUF->type == htons(UIP_ETHTYPE_IP))
    {
     uip_arp_ipin();
     uip_input();
     if(uip_len > 0)
     {
      uip_arp_out();
      tapdev_send();
     }
    }
    else if(BUF->type == htons(UIP_ETHTYPE_ARP))
    {
     uip_arp_arpin();
     if(uip_len > 0)
     {
      tapdev_send();
     }
    }

   }
   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();
     }
    }

#if UIP_UDP
    for(i = 0; i < UIP_UDP_CONNS; i++)
    {
     uip_udp_periodic(i);
     if(uip_len > 0)
     {
      uip_arp_out();
      tapdev_send();
     }
    }
#endif /* UIP_UDP */

    /* Call the ARP timer function every 10 seconds. */
    if(timer_expired(&arp_timer))
    {
     timer_reset(&arp_timer);
     uip_arp_timer();
    }
   }
  }
  return 0;
}

 

int main(int argc, char* argv[])
{
 
   uIP_Net_Init();

   while(1)
   {
    UipPro();  
   }


  return 0;
}

 

通过DHCP获取动态IP,接可以在同一台机器上测试了。

注:winpcap不能抓自己发给自己的数据包,需要把本机IP加入路由表,但加入后,本地TCP通讯又不正常了。

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值