contiki学习笔记-UDP-Client原厂代码分析

来源:互联网 发布:mac 图形驱动 编辑:程序博客网 时间:2024/04/28 17:02

      接触contiki一段时间了,但是苦于资料比较少,而且基本上都是入门级别的资料,所以学习起来非常的吃力。于是只能拿官方的实例代码进行剖析。对于udp-client.c这个文件先进行分析。

      首先看一下整个的流程。

     

PROCESS_THREAD(udp_client_process, ev, data){  static struct etimer et;//定时器  uip_ipaddr_t ipaddr;//地址  PROCESS_BEGIN();  PRINTF("UDP client process started\n");#if UIP_CONF_ROUTER  set_global_address();#endif  print_local_addresses();//打印所有本地可用的地址  static resolv_status_t status = RESOLV_STATUS_UNCACHED;  while(status != RESOLV_STATUS_CACHED) {    status = set_connection_address(&ipaddr);//设定连接的远端IP地址/* 处理一些异常情况*/    if(status == RESOLV_STATUS_RESOLVING) {      PROCESS_WAIT_EVENT_UNTIL(ev == resolv_event_found);    } else if(status != RESOLV_STATUS_CACHED) {      PRINTF("Can't get connection address.\n");      PROCESS_YIELD();    }  }  /* new connection with remote host 这里和普通的socket编程一样,先申请一个conn,再进行绑定,其中conn中包括远端的IP地址 */  client_conn = udp_new(&ipaddr, UIP_HTONS(3000), NULL);  udp_bind(client_conn, UIP_HTONS(3001));  PRINTF("Created a connection with the server ");  PRINT6ADDR(&client_conn->ripaddr);//将一个IPV6地址打印出来  PRINTF(" local/remote port %u/%u\n",UIP_HTONS(client_conn->lport), UIP_HTONS(client_conn->rport));  etimer_set(&et, SEND_INTERVAL);//设定定时器  while(1) {    PROCESS_YIELD();    if(etimer_expired(&et)) {//定时器到时间      timeout_handler();      etimer_restart(&et);    } else if(ev == tcpip_event) {//收到响应信息      tcpip_handler();    }  }  PROCESS_END();}
         我们再对其中的几个函数进行分析。

       

static voidprint_local_addresses(void){  int i;  uint8_t state;  PRINTF("Client IPv6 addresses: ");  for(i = 0; i < UIP_DS6_ADDR_NB; i++) {    state = uip_ds6_if.addr_list[i].state;    if(uip_ds6_if.addr_list[i].isused &&       (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) {      PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr);      PRINTF("\n");    }  }}
       

       这个函数的主要作用就是打印一下可用的IP地址。UIP_DS6_ADDR_NB这个应该是IPV6的地址的数量,在原厂代码中为3.uip_ds6_if是uip-ds6中定义的一个数据结构,包含了所有的接口变量。它的格式为

typedef struct uip_ds6_netif {  uint32_t link_mtu;  uint8_t cur_hop_limit;  uint32_t base_reachable_time; /* in msec */  uint32_t reachable_time;      /* in msec */  uint32_t retrans_timer;       /* in msec */  uint8_t maxdadns;  uip_ds6_addr_t addr_list[UIP_DS6_ADDR_NB];  uip_ds6_aaddr_t aaddr_list[UIP_DS6_AADDR_NB];  uip_ds6_maddr_t maddr_list[UIP_DS6_MADDR_NB];} uip_ds6_netif_t;
    

    addr_list中就是所有的IPV6地址。for循环就是将其中的IPV6地址都查找一遍,看它的状态。IPV6的地址有三种状态,一种是PREFERRED,代表IPV6地址可用。第二种是TENTATIVE,代表未知。最后一种代表其他主机正在使用,DEPRECATED。

  

static resolv_status_tset_connection_address(uip_ipaddr_t *ipaddr){#ifndef UDP_CONNECTION_ADDR#if RESOLV_CONF_SUPPORTS_MDNS#define UDP_CONNECTION_ADDR       contiki-udp-server.local#elif UIP_CONF_ROUTER#define UDP_CONNECTION_ADDR       aaaa:0:0:0:0212:7404:0004:0404#elseRESOLV_CONF_SUPPORTS_MDNS#define UDP_CONNECTION_ADDR       contiki-udp-server.local#elif#define UDP_CONNECTION_ADDR       fe80:0:0:0:6466:6666:6666:6666#endif#endif /* !UDP_CONNECTION_ADDR */#define _QUOTEME(x) #x#define QUOTEME(x) _QUOTEME(x)  resolv_status_t status = RESOLV_STATUS_ERROR;  if(uiplib_ipaddrconv(QUOTEME(UDP_CONNECTION_ADDR), ipaddr) == 0) {//如果不能转换成Ipv6地址成功    uip_ipaddr_t *resolved_addr = NULL;    status = resolv_lookup(QUOTEME(UDP_CONNECTION_ADDR),&resolved_addr);    if(status == RESOLV_STATUS_UNCACHED || status == RESOLV_STATUS_EXPIRED) {      PRINTF("Attempting to look up %s\n",QUOTEME(UDP_CONNECTION_ADDR));      resolv_query(QUOTEME(UDP_CONNECTION_ADDR));      status = RESOLV_STATUS_RESOLVING;    } else if(status == RESOLV_STATUS_CACHED && resolved_addr != NULL) {      PRINTF("Lookup of \"%s\" succeded!\n",QUOTEME(UDP_CONNECTION_ADDR));
   这段代码看似复杂,实现的功能相当的简单,就是将IPV6地址赋值到ipaddr当中。首先定义UDP_CONNECTION_ADDR变量,这个变量的作用就是放置文本型的IPV6地址。为了方便,需要将文本型的(也就是直接给的那种128位地址)转换成通用的格式。这一大段定义不好阅读,就是根据各自的情况来进行赋值。QUOTEME(x)的作用是将一个地址转换成字符串。在这里,转换的过程相当的复杂,有各自状态,这里就不详细说了。if内是转换不成功的情况,会针对不成功的情况进行处理。

0 0