博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Lwm2m的server分析
阅读量:4215 次
发布时间:2019-05-26

本文共 7573 字,大约阅读时间需要 25 分钟。

Wakaama 是lwm2m协议的一种实现,其源码路径为wakaama。lwm2m的实现分为server和client。编译server的方法为:cmake [wakaama directory]/examples/servermake./lwm2mserver [Options]我们看看server的makerfile是怎么写的#要求cmake的版本必须是2.8cmake_minimum_required (VERSION 2.8)project (lwm2mserver C)#不支持dtls特性if(DTLS) message(FATAL_ERROR "DTLS option is not supported." ) endif()include(${CMAKE_CURRENT_LIST_DIR}/../../core/wakaama.cmake) include(${CMAKE_CURRENT_LIST_DIR}/../shared/shared.cmake)#定义宏add_definitions(-DLWM2M_SERVER_MODE) add_definitions(${SHARED_DEFINITIONS} ${WAKAAMA_DEFINITIONS})include_directories (${WAKAAMA_SOURCES_DIR} ${SHARED_INCLUDE_DIRS})#原来server就一个源文件SET(SOURCES ${CMAKE_CURRENT_LIST_DIR}/lwm2mserver.c    )#编译成可执行文件add_executable(${PROJECT_NAME} ${SOURCES} ${WAKAAMA_SOURCES} ${SHARED_SOURCES})# Add WITH_LOGS to debug variant set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY COMPILE_DEFINITIONS $<$
:WITH_LOGS>)SOURCE_GROUP(wakaama FILES ${WAKAAMA_SOURCES}) 我们看看这个唯一的源文件的main函数int main(int argc, char *argv[]){ int sock; fd_set readfds; struct timeval tv; int result; lwm2m_context_t * lwm2mH = NULL; int i; connection_t * connList = NULL; int addressFamily = AF_INET6; int opt; const char * localPort = LWM2M_STANDARD_PORT_STR;#main函数支持的子命令 command_desc_t commands[] = { {"list", "List registered clients.", NULL, prv_output_clients, NULL}, {"read", "Read from a client.", " read CLIENT# URI\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri to read such as /3, /3/0/2, /1024/11, /1024/0/1\r\n" "Result will be displayed asynchronously.", prv_read_client, NULL}, {"disc", "Discover resources of a client.", " disc CLIENT# URI\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri to discover such as /3, /3/0/2, /1024/11, /1024/0/1\r\n" "Result will be displayed asynchronously.", prv_discover_client, NULL}, {"write", "Write to a client.", " write CLIENT# URI DATA\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri to write to such as /3, /3/0/2, /1024/11, /1024/0/1\r\n" " DATA: data to write\r\n" "Result will be displayed asynchronously.", prv_write_client, NULL}, }; opt = 1; { if (argv[opt] == NULL || argv[opt][0] != '-' || argv[opt][2] != 0) { print_usage(); return 0; } switch (argv[opt][1]) { case '4': addressFamily = AF_INET; break; case 'l': opt++; if (opt >= argc) { print_usage(); return 0; } localPort = argv[opt]; break; default: print_usage(); return 0; } opt += 1; } #建立一个socket,默认是用AF_INET即netlinksock = create_socket(localPort, addressFamily); if (sock < 0) { fprintf(stderr, "Error opening socket: %d\r\n", errno); return -1; }#初始化lwm2m lwm2mH = lwm2m_init(NULL); if (NULL == lwm2mH) { fprintf(stderr, "lwm2m_init() failed\r\n"); return -1; }#设置信号量SIGNIT的回调函数 signal(SIGINT, handle_sigint); for (i = 0 ; commands[i].name != NULL ; i++) { commands[i].userData = (void *)lwm2mH; } fprintf(stdout, "> "); fflush(stdout); lwm2m_set_monitoring_callback(lwm2mH, prv_monitor_callback, lwm2mH);#看见main函数就是一个死循环,直到收到SIGINT信号后将g_quit修改成0 才退出. while (0 == g_quit) { FD_ZERO(&readfds); FD_SET(sock, &readfds); FD_SET(STDIN_FILENO, &readfds); tv.tv_sec = 60; tv.tv_usec = 0; result = lwm2m_step(lwm2mH, &(tv.tv_sec)); if (result != 0) { fprintf(stderr, "lwm2m_step() failed: 0x%X\r\n", result); return -1; }#最终要是这里开始调用select来监听client的通信 result = select(FD_SETSIZE, &readfds, 0, 0, &tv);#select发生错误的情况 if ( result < 0 ) { if (errno != EINTR) { fprintf(stderr, "Error in select(): %d\r\n", errno); } }#select正常返回的情况 else if (result > 0) { uint8_t buffer[MAX_PACKET_SIZE]; int numBytes;#检查是否sock这个句柄被设置了 if (FD_ISSET(sock, &readfds)) { struct sockaddr_storage addr; socklen_t addrLen; addrLen = sizeof(addr);#读取sock返回的信息 numBytes = recvfrom(sock, buffer, MAX_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrLen); if (numBytes == -1) { fprintf(stderr, "Error in recvfrom(): %d\r\n", errno); } else { char s[INET6_ADDRSTRLEN]; in_port_t port; connection_t * connP; s[0] = 0;#判断netlink是ipv4还是ipv6,这里假定是ipv4 if (AF_INET == addr.ss_family) { struct sockaddr_in *saddr = (struct sockaddr_in *)&addr; inet_ntop(saddr->sin_family, &saddr->sin_addr, s, INET6_ADDRSTRLEN); port = saddr->sin_port; } else if (AF_INET6 == addr.ss_family) { struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)&addr; inet_ntop(saddr->sin6_family, &saddr->sin6_addr, s, INET6_ADDRSTRLEN); port = saddr->sin6_port; } fprintf(stderr, "%d bytes received from [%s]:%hu\r\n", numBytes, s, ntohs(port));#将数据读到buffer中 output_buffer(stderr, buffer, numBytes, 0);#判断这个是新连接还是就连接 connP = connection_find(connList, &addr, addrLen); if (connP == NULL) {#如果是新连接则建立连接后,将新连接保存到connlist中 connP = connection_new_incoming(connList, sock, (struct sockaddr *)&addr, addrLen); if (connP != NULL) { connList = connP; } } if (connP != NULL) {#只要前面的连接有效,则开始处理client发送过来的包 lwm2m_handle_packet(lwm2mH, buffer, numBytes, connP); } } }#如果是STDIN_FILENO 这个句柄被设置,则出来这个句柄中读到的command else if (FD_ISSET(STDIN_FILENO, &readfds)) { numBytes = read(STDIN_FILENO, buffer, MAX_PACKET_SIZE - 1); if (numBytes > 1) { buffer[numBytes] = 0; handle_command(commands, (char*)buffer); fprintf(stdout, "\r\n"); } if (g_quit == 0) { fprintf(stdout, "> "); fflush(stdout); } else { fprintf(stdout, "\r\n"); } } } } lwm2m_close(lwm2mH); close(sock); connection_free(connList);#ifdef MEMORY_TRACE if (g_quit == 1) { trace_print(0, 1); }#endif return 0;}

 

转载地址:http://wvnmi.baihongyu.com/

你可能感兴趣的文章
手动12 - 安装php加速器 Zend OPcache
查看>>
set theme -yii2
查看>>
yii2 - controller
查看>>
yii2 - 增加actions
查看>>
php图像处理函数大全(缩放、剪裁、缩放、翻转、旋转、透明、锐化的实例总结)
查看>>
magento url中 uenc 一坨编码 base64
查看>>
强大的jQuery焦点图无缝滚动走马灯特效插件cxScroll
查看>>
Yii2.0 数据库查询
查看>>
yii2 db 操作
查看>>
mongodb group 有条件的过滤组合个数。
查看>>
关于mongodb的 数组分组 array group
查看>>
MongoDB新的数据统计框架介绍
查看>>
mongodb 增加全文检索索引
查看>>
mysql数据库主从同步的问题解决方法
查看>>
QC数据库表结构
查看>>
测试工具厂商的编程语言什么时候“退休”?
查看>>
资源监控工具 - Hyperic HQ
查看>>
LoadRunner中Concurrent与Simultaneous的区别
查看>>
SiteScope - Agentless监控
查看>>
欢迎加入【亿能测试快讯】邮件列表!
查看>>