一、Rtnetlink

  Rtnetlink 允许对内核路由表进行读和更改,它用于内核与各个子系统之间(路由子系统、IP地址、链接参数等)的通信,

用户空间可以通过NET_LINK_ROUTER socket 与内核进行通信,该过程基于标准的netlink消息进行。

  注:netlink用法在上一篇博文中有提到 http://www.cnblogs.com/wenqiang/p/6306727.html

一些rtnetlink消息在初始头后有一些可选属性,下面是该属性的结构:

  1. struct rtattr {
  2. unsigned short rta_len; /* Length of option */
  3. unsigned short rta_type; /* Type of option */
  4. /* Data follows */
  5. };

操作这些属性只可以用RTA_*这些宏来造作

  1. /* Macros to handle rtattributes */
  2.  
  3. /* 对齐 */
  4. #define RTA_ALIGNTO 4
  5. #define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) )
  6.  
  7. /* 判断是否为合法的路由属性 */
  8. #define RTA_OK(rta,len) ((len) >= (int)sizeof(struct rtattr) && \
  9. (rta)->rta_len >= sizeof(struct rtattr) && \
  10. (rta)->rta_len <= (len))
  11.  
  12. /* 获取下一个rtattr的首地址*/
  13. #define RTA_NEXT(rta,attrlen) ((attrlen) -= RTA_ALIGN((rta)->rta_len), \
  14. (struct rtattr*)(((char*)(rta)) + RTA_ALIGN((rta)->rta_len)))
  15.  
  16. /* 返回加上 rtattr header的总长度 */
  17. #define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
  18.  
  19. /* 返回数据对齐的最小值 */
  20. #define RTA_SPACE(len) RTA_ALIGN(RTA_LENGTH(len))
  21.  
  22. /* 返回属性数据部分首地址 */
  23. #define RTA_DATA(rta) ((void*)(((char*)(rta)) + RTA_LENGTH(0)))
  24.  
  25. /*返回属性数据部分的长度 */
  26. #define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
  27.  
  28. /*****************************************************************
  29. ******************************************************************/
  30. rtnetlink_socket = socket(AF_NETLINK, int socket_type, NETLINK_ROUTE);
  31.  
  32. int RTA_OK(struct rtattr *rta, int rtabuflen);
  33.  
  34. void *RTA_DATA(struct rtattr *rta);
  35.  
  36. unsigned int RTA_PAYLOAD(struct rtattr *rta);
  37.  
  38. struct rtattr *RTA_NEXT(struct rtattr *rta, unsigned int rtabuflen);
  39.  
  40. unsigned int RTA_LENGTH(unsigned int length);
  41.  
  42. unsigned int RTA_SPACE(unsigned int length);

Rtnetlink 由下面这些消息类型构成(新加在标准的netlink消息上)
(1)#RTM_NEWLINK, RTM_DELLINK, RTM_GETLINK
创建或者删除一个特定的网络接口,或者从一个特定的网络接口上获得信息。
这些消息含有一个ifinfomsg类型的结构,紧跟在后面的是一系列的rtattr结构。

  1. /*****************************************************************
  2. * Link layer specific messages.
  3. ****/
  4.  
  5. /* struct ifinfomsg
  6. * passes link level specific information, not dependent
  7. * on network protocol.
  8. */
  9.  
  10. struct ifinfomsg {
  11. unsigned char ifi_family; /* AF_UNSPEC */
  12. unsigned short ifi_type; /* Device type */
  13. int ifi_index; /* Interface index */
  14. unsigned int ifi_flags; /* Device flags */
  15. unsigned int ifi_change; /* change mask */
  16. };
  17. /*
  18. * ifi_family: 接口地址类型
  19. * ifi_type: 设备类型
  20. * ifi_index: 是结构唯一的索引
  21. * ifi_flags: 设备标志,可以看netdevice 结构
  22. * ifi_change: 保留值,通常设置为0xFFFFFFFF
  23. */
  24.  
  25. /*
  26. ifi_type代表硬件设备的类型:
  27. ARPHRD_ETHER 10M以太网
  28. ARPHRD_PPP PPP拨号
  29. ARPHRDLOOPBACK 环路设备
  30.  
  31. ifi_flags包含设备的一些标志:
  32. IFF_UP 接口正在运行
  33. IFF_BROADCAST 有效的广播地址集
  34. IFF_DEBUG 内部调试标志
  35. IFF_LOOPBACK 这是自环接口
  36. IFF_POINTOPOINT 这是点到点的链路设备
  37. IFF_RUNNING 资源已分配
  38. IFF_NOARP 无arp协议,没有设置第二层目的地址
  39. IFF_PROMISC 接口为杂凑(promiscuous)模式
  40. IFF_NOTRAILERS 避免使用trailer
  41. IFF_ALLMULTI 接收所有组播(multicast)报文
  42. IFF_MASTER 主负载平衡群(bundle)
  43. IFF_SLAVE 从负载平衡群(bundle)
  44. IFF_MULTICAST 支持组播(multicast)
  45. IFF_PORTSEL 可以通过ifmap选择介质(media)类型
  46. IFF_AUTOMEDIA 自动选择介质
  47. IFF_DYNAMIC 接口关闭时丢弃地址
  48.  
  49. Routing attributes(rtattr部分属性,rta_type)
  50.  
  51. rta_type value type description
  52. ──────────────────────────────────────────────────────────
  53. IFLA_UNSPEC - 未说明,未指定的数据
  54. IFLA_ADDRESS hardware address L2硬件地址
  55. IFLA_BROADCAST hardware address L2广播地址.
  56. IFLA_IFNAME asciiz string char型设备名.
  57. IFLA_MTU unsigned int MTU of the device.
  58. IFLA_LINK int Link type.
  59. IFLA_QDISC asciiz string Queueing discipline.
  60. IFLA_STATS see below struct rtnl_link_stats的设备信息
  61.  
  62. //用来获取ifinfomsg后面的rtattr结构
  63. #define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
  64. */

(2)# RTM_NEWADDR, RTM_DELADDR, RTM_GETADDR

添加,删除或者接收一个和接口相关的IP地址的信息。
在linux2.2中,一个网口是可以有多个IP地址信息的。这些消息含有一个ifaddrmsg类型的结构,紧跟在后面的是一系列的rtattr结构。

  1. struct ifaddrmsg {
  2. unsigned char ifa_family; /* Address type */
  3. unsigned char ifa_prefixlen; /* Prefixlength of address */
  4. unsigned char ifa_flags; /* Address flags */
  5. unsigned char ifa_scope; /* Address scope */
  6. int ifa_index; /* Interface index */
  7. };
  8. /*
  9. * ifa_family: 地址类型(通常为AF_INET or AF_INET6))
  10. * ifa_prefixlen: 地址的地址掩码长度,如果改地址定义在这个family
  11. * ifa_flags:
  12. * ifa_scope: 地址的作用域
  13. * ifa_index: 接口索引与接口地址关联
  14. */
  15.  
  16. /*
  17. Attributes (rtattr部分属性,rta_type)
  18. rta_type value type description
  19. ─────────────────────────────────────────────────────────────
  20. IFA_UNSPEC - unspecified.
  21. IFA_ADDRESS raw protocol address 接口地址 interface address
  22. IFA_LOCAL raw protocol address 本地地址 local address
  23. IFA_LABEL asciiz string 接口名称 name of the interface
  24. IFA_BROADCAST raw protocol address 广播 broadcast address.
  25. IFA_ANYCAST raw protocol address anycast address
  26. IFA_CACHEINFO struct ifa_cacheinfo Address information.
  27.  
  28. */

(3)#RTM_NEWROUTE, RTM_DELROUTE, RTM_GETROUTE

创建,删除或者获取网络设备的路由信息;这些消息包含一个rtmsg结构,其后跟数目可选的rtattr结构。
对于RTM_GETROUTE,设置rtm_dst_len以及rtm_src_len为0表示获取指定路由表的所有条目(entries)。
其它的成员,除了rtm_table、rtm_protocol,0是通配符

  1. struct rtmsg {
  2. unsigned char rtm_family;
  3. unsigned char rtm_dst_len;
  4. unsigned char rtm_src_len;
  5. unsigned char rtm_tos;
  6.  
  7. unsigned char rtm_table; /* Routing table id */
  8. unsigned char rtm_protocol; /* Routing protocol; see below */
  9. unsigned char rtm_scope; /* See below */
  10. unsigned char rtm_type; /* See below */
  11.  
  12. unsigned rtm_flags;
  13. };
  14.  
  15. rtm_type Route type
  16. ───────────────────────────────────────────────────────────
  17. RTN_UNSPEC unknown route /*位置路由*/
  18. RTN_UNICAST a gateway or direct route /* 网关或直连路由 */
  19. RTN_LOCAL a local interface route /* 本地接口路由 */
  20. RTN_BROADCAST a local broadcast route (sent as a broadcast) /* 本地广播式接收,发送 */
  21. RTN_ANYCAST a local broadcast route (sent as a unicast) /* 本地单播路由 */
  22. RTN_MULTICAST a multicast route /* 多播路由 */
  23. RTN_BLACKHOLE a packet dropping route /* 丢弃 */
  24. RTN_UNREACHABLE an unreachable destination /* 目标不可达 */
  25. RTN_PROHIBIT a packet rejection route /* 拒绝 */
  26. RTN_THROW continue routing lookup in another table /* 不在本表 */
  27. RTN_NAT a network address translation rule /* nat */
  28. RTN_XRESOLVE refer to an external resolver (not implemented)
  29.  
  30. rtm_protocol Route origin.
  31. ───────────────────────────────────────
  32. RTPROT_UNSPEC unknown
  33. RTPROT_REDIRECT by an ICMP redirect (currently unused) /* 通过icmp转发建立路由 (目前没用)*/
  34. RTPROT_KERNEL by the kernel /* 通过内核建立路由 */
  35. RTPROT_BOOT during boot /* 启动时建立路由 */
  36. RTPROT_STATIC by the administrator /* 管理员建立 */
  37.  
  38. rtm_scope is the distance to the destination:
  39.  
  40. RT_SCOPE_UNIVERSE global route
  41. RT_SCOPE_SITE interior route in the local autonomous system
  42. RT_SCOPE_LINK route on this link
  43. RT_SCOPE_HOST route on the local host
  44. RT_SCOPE_NOWHERE destination doesn't exist
  45.  
  46. /* 用户可用范围 */
  47. RT_SCOPE_UNIVERSE ~ RT_SCOPE_SITE are available to the user.
  48.  
  49. The rtm_flags have the following meanings:
  50.  
  51. RTM_F_NOTIFY if the route changes, notify the user via rtnetlink
  52. RTM_F_CLONED route is cloned from another route
  53. RTM_F_EQUALIZE a multipath equalizer (not yet implemented)
  54.  
  55. rtm_table specifies the routing table
  56.  
  57. RT_TABLE_UNSPEC an unspecified routing table /* 0 未指定的表 */
  58. RT_TABLE_DEFAULT the default table /* 253 默认表 */
  59. RT_TABLE_MAIN the main table /* 254 main 表 */
  60. RT_TABLE_LOCAL the local table /* 255 local 表 */
  61.  
  62. //用户可以使用 RT_TABLE_UNSPEC 到 RT_TABLE_DEFAULT 之间的任意值
  63.  
  64. Attributes
  65.  
  66. rta_type value type description
  67. ──────────────────────────────────────────────────────────────
  68. RTA_UNSPEC - ignored.
  69. RTA_DST protocol address Route destination address. /* 目的 */
  70. RTA_SRC protocol address Route source address. /* 源地址 */
  71. RTA_IIF int Input interface index. /* 输入设备 index */
  72. RTA_OIF int Output interface index.
  73. RTA_GATEWAY protocol address The gateway of the route /* 网关 */
  74. RTA_PRIORITY int Priority of route. /* 优先级 */
  75. RTA_PREFSRC
  76. RTA_METRICS int Route metric /* 路由metric 值*/
  77. RTA_MULTIPATH
  78. RTA_PROTOINFO
  79. RTA_FLOW
  80. RTA_CACHEINFO

一面是一个具体实例:

  1. /*********************************************************
  2. * Filename: nl_netinfo.c
  3. * Author: zhangwj
  4. * Date:
  5. * Descripte:
  6. * Email:
  7. * Warnning:
  8. **********************************************************/
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <sys/types.h> /* See NOTES */
  13. #include <sys/socket.h>
  14. #include <arpa/inet.h>
  15. #include <sys/epoll.h>
  16. #include <linux/netlink.h>
  17. #include <linux/rtnetlink.h>
  18. #include <linux/route.h>
  19. #include <errno.h>
  20.  
  21. #define EPOLL_LISTEN_MAX_CNT 256
  22. #define EPOLL_LISTEN_TIMEOUT 500
  23.  
  24. int g_nlfd = -;
  25. int g_epollfd = -;
  26.  
  27. void parse_rtattr(struct rtattr **tb, int max, struct rtattr *attr, int len)
  28. {
  29. for (; RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) {
  30. if (attr->rta_type <= max) {
  31. tb[attr->rta_type] = attr;
  32. }
  33. }
  34. }
  35.  
  36. void nl_netroute_handle(struct nlmsghdr *nlh)
  37. {
  38. int len;
  39. struct rtattr *tb[RTA_MAX + ];
  40. struct rtmsg *rt;
  41. char tmp[];
  42.  
  43. bzero(tb, sizeof(tb));
  44. rt = NLMSG_DATA(nlh);
  45. len = nlh->nlmsg_len - NLMSG_SPACE(sizeof(*rt));
  46. parse_rtattr(tb, RTA_MAX, RTM_RTA(rt), len);
  47. printf("%s: ", (nlh->nlmsg_type==RTM_NEWROUTE)?"NEWROUT":"DELROUT");
  48. if (tb[RTA_DST] != NULL) {
  49. inet_ntop(rt->rtm_family, RTA_DATA(tb[RTA_DST]), tmp, sizeof(tmp));
  50. printf("DST: %s ", tmp);
  51. }
  52. if (tb[RTA_SRC] != NULL) {
  53. inet_ntop(rt->rtm_family, RTA_DATA(tb[RTA_SRC]), tmp, sizeof(tmp));
  54. printf("SRC: %s ", tmp);
  55. }
  56. if (tb[RTA_GATEWAY] != NULL) {
  57. inet_ntop(rt->rtm_family, RTA_DATA(tb[RTA_GATEWAY]), tmp, sizeof(tmp));
  58. printf("GATEWAY: %s ", tmp);
  59. }
  60. printf("\n");
  61. }
  62.  
  63. void nl_netifinfo_handle(struct nlmsghdr *nlh)
  64. {
  65. int len;
  66. struct rtattr *tb[IFLA_MAX + ];
  67. struct ifinfomsg *ifinfo;
  68.  
  69. bzero(tb, sizeof(tb));
  70. ifinfo = NLMSG_DATA(nlh);
  71. len = nlh->nlmsg_len - NLMSG_SPACE(sizeof(*ifinfo));
  72. parse_rtattr(tb, IFLA_MAX, IFLA_RTA (ifinfo), len);
  73.  
  74. printf("%s: %s ", (nlh->nlmsg_type==RTM_NEWLINK) ? "NEWLINK" : "DELLINK", (ifinfo->ifi_flags & IFF_UP) ? "up" : "down");
  75. if(tb[IFLA_IFNAME]) {
  76. printf("%s", RTA_DATA(tb[IFLA_IFNAME]));
  77. }
  78. printf("\n");
  79. }
  80.  
  81. void nl_netifaddr_handle(struct nlmsghdr *nlh)
  82. {
  83. int len;
  84. struct rtattr *tb[IFA_MAX + ];
  85. struct ifaddrmsg *ifaddr;
  86. char tmp[];
  87.  
  88. bzero(tb, sizeof(tb));
  89. ifaddr = NLMSG_DATA(nlh);
  90. len =nlh->nlmsg_len - NLMSG_SPACE(sizeof(*ifaddr));
  91. parse_rtattr(tb, IFA_MAX, IFA_RTA (ifaddr), len);
  92.  
  93. printf("%s ", (nlh->nlmsg_type == RTM_NEWADDR)? "NEWADDR":"DELADDR");
  94. if (tb[IFA_LABEL] != NULL) {
  95. printf("%s ", RTA_DATA(tb[IFA_LABEL]));
  96. }
  97. if (tb[IFA_ADDRESS] != NULL) {
  98. inet_ntop(ifaddr->ifa_family, RTA_DATA(tb[IFA_ADDRESS]), tmp, sizeof(tmp));
  99. printf("%s ", tmp);
  100. }
  101. printf("\n");
  102. }
  103.  
  104. void nl_netlink_handle(int fd)
  105. {
  106. int r_size;
  107. socklen_t len = ;
  108. char buff[] = {};
  109. struct sockaddr_nl addr;
  110. struct nlmsghdr *nlh;
  111.  
  112. while()
  113. {
  114. len = sizeof(addr);
  115. r_size = recvfrom(fd, (void *)buff, sizeof(buff), , (struct sockaddr *)&addr, &len);
  116. nlh = (struct nlmsghdr *)buff;
  117. for(; NLMSG_OK(nlh, r_size); nlh = NLMSG_NEXT(nlh, r_size))
  118. {
  119. switch(nlh->nlmsg_type) {
  120. case NLMSG_DONE:
  121. case NLMSG_ERROR:
  122. break;
  123. case RTM_NEWLINK: /* */
  124. case RTM_DELLINK:
  125. nl_netifinfo_handle(nlh);
  126. break;
  127. case RTM_NEWADDR:
  128. case RTM_DELADDR: /* */
  129. nl_netifaddr_handle(nlh);
  130. break;
  131. case RTM_NEWROUTE:
  132. case RTM_DELROUTE: /* */
  133. nl_netroute_handle(nlh);
  134. break;
  135. default:
  136. break;
  137. }
  138. }
  139. }
  140. }
  141.  
  142. void epoll_event_handle(void)
  143. {
  144. int i = ;
  145. int fd_cnt = ;
  146. int sfd;
  147. struct epoll_event events[EPOLL_LISTEN_MAX_CNT];
  148.  
  149. memset(events, , sizeof(events));
  150. while()
  151. {
  152. /* wait epoll event */
  153. fd_cnt = epoll_wait(g_epollfd, events, EPOLL_LISTEN_MAX_CNT, EPOLL_LISTEN_TIMEOUT);
  154. for(i = ; i < fd_cnt; i++)
  155. {
  156. sfd = events[i].data.fd;
  157. if(events[i].events & EPOLLIN)
  158. {
  159. if (sfd == g_nlfd)
  160. {
  161. nl_netlink_handle(sfd);
  162. }
  163. }
  164. }
  165. }
  166. }
  167.  
  168. int epoll_add_fd(int fd)
  169. {
  170. struct epoll_event ev;
  171.  
  172. ev.data.fd = fd;
  173. ev.events = EPOLLIN | EPOLLET;
  174.  
  175. if (epoll_ctl(g_epollfd, EPOLL_CTL_ADD, fd, &ev) < ) {
  176. perror("epoll add fd error");
  177. return -;
  178. }
  179.  
  180. printf("epoll add fd[%d] success\n", fd);
  181. return ;
  182. }
  183.  
  184. int init_epoll_fd()
  185. {
  186. int epollfd = -;
  187.  
  188. epollfd = epoll_create(EPOLL_LISTEN_MAX_CNT);
  189. if (epollfd < ) {
  190. perror("epoll create failure!...");
  191. return -;
  192. }
  193. g_epollfd = epollfd;
  194.  
  195. printf("epool create fd [%d] success\n", epollfd);
  196. return g_epollfd;
  197. }
  198.  
  199. int init_nl_sockfd()
  200. {
  201. int ret = ;
  202. int nlfd = -;
  203. struct sockaddr_nl sa;
  204.  
  205. /* open a netlink fd */
  206. nlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  207. if (nlfd < ) {
  208. perror("create netlink socket failure");
  209. return -;
  210. }
  211.  
  212. memset(&sa, , sizeof(sa));
  213. sa.nl_family = AF_NETLINK;
  214. sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE;
  215.  
  216. /* bind netlink */
  217. ret = bind(nlfd, (struct sockaddr *)&sa, sizeof(sa));
  218. if (ret < ) {
  219. perror("bind nlfd error");
  220. close(nlfd);
  221. return -;
  222. }
  223.  
  224. if (epoll_add_fd(nlfd)) {
  225. close(nlfd);
  226. return -;
  227. }
  228. g_nlfd = nlfd;
  229.  
  230. printf("netlink create fd [%d] success\n", nlfd);
  231. return nlfd;
  232. }
  233.  
  234. int main(int argc, char **argv)
  235. {
  236. if (init_epoll_fd() < ) { /* 创建epoll 监听fd */
  237. return -;
  238. }
  239.  
  240. if (init_nl_sockfd() < ) { /* 创建netlink */
  241. return -;
  242. }
  243.  
  244. /* 循环接收处理 */
  245. epoll_event_handle();
  246.  
  247. return ;
  248. }

参考资料:

http://www.man7.org/linux/man-pages/man7/rtnetlink.7.html

http://www.man7.org/linux/man-pages/man3/rtnetlink.3.html

linux 获取网络状态信息(Rtnetlink)的更多相关文章

  1. Android获取网络状态

    Android获取网络状态 学习自 https://developer.android.google.cn/reference/android/net/ConnectivityManager http ...

  2. [android] android 获取网络连接信息

    效果图:  工具类 /** * 获取网络连接信息 * * 根据NetworkInfo可以知道有很多的连接方式和信息 * * ① 当没有任何可用网络的时候,networkinfo为null 判断netw ...

  3. React Native之Fetch简单封装、获取网络状态

    1.Fetch的使用 fetch的使用非常简单,只需传入请求的url fetch('https://facebook.github.io/react-native/movies.json'); 当然是 ...

  4. [React Native]获取网络状态

    使用React Native,可以使用NetInfo API获取手机当前的各个网络状态. componentWillMount() { NetInfo.fetch().done((status)=&g ...

  5. iOS 获取网络状态

    在iOS开发者,获取网络状态比较常用 -(NSString *)getNetWorkStates{ UIApplication *app = [UIApplication sharedApplicat ...

  6. android开发获取网络状态,wifi,wap,2g,3g.工具类(一)

    android开发获取网络状态整理: package com.gzcivil.utils; import android.content.Context; import android.net.Con ...

  7. 微信小程序 --- 获取网络状态

    获取网络状态:wx.getNetworkType btnclick:function(){ wx.getNetworkType({ success:function(res){ console.log ...

  8. C#获取网络状态

    /// <summary> /// 获取网络状态 /// </summary> /// <param name="ip">目标IP地址</ ...

  9. Linux网络编程之"获取网络天气信息"

    需求分析: 1.需要Linux c 网络编程基础, 2.需要了解 http 协议 3.需要天气信息相关api(可以从阿里云上购买,很便宜的!) 4.需要cJSON解析库(因为获取到的天气信息一般是用c ...

随机推荐

  1. SpriteBuilder中本地化的局限性

    最后,App中的(图片)logo仍然保留在英语格式. 未来SpriteBuilder将计划支持本地化资源文件,但是写作该篇的时候估计还没有实现. 你现在必须使用正规的iOS app的国际化技术来支持本 ...

  2. Erlang Rebar 使用指南之四:依赖管理

    Erlang Rebar 使用指南之四:依赖管理 全文目录: https://github.com/rebar/rebar/wiki 本章链接: https://github.com/rebar/re ...

  3. 高斯混合模型和EM算法

    使用期望最大化算法(Expectation-Maximization)来进行密度估计(density estimation). 与k-means一样,给定的训练样本是,我们将隐含类别标签用表示.与k- ...

  4. Xcode出现may cause a leak非忽略的解决方法

    前面提到可以把may cause a leak当成安静的美代码忽略掉,但其实还是有另一种方法滴. 你可以用如下代码替换以消除該警告: [xxx performSelector:_cmd withObj ...

  5. obj-c编程15[Cocoa实例01]:一个会发声的随机数生成器

    哇!终于到了obj-c编程系列的第15篇喽,一路走过来满不容易的哦!(怎么个意思,这才哪到哪啊!),为了能够更好的练习obj-c在Cocoa框架上的编程,接下来会以N篇Cocoa实例的博文来巩固和记忆 ...

  6. Mac OS X安装native gem提示找不到 dyld_stub_binding_helper

    在Mac OS X10.10下sudo gem install curses 返回如下错误: apple@kissAir: ruby_src$sudo gem install curses Passw ...

  7. Java小技巧输出26个英文字母

    相信有的童鞋写到过与字母有关的小东西,是否有写过全部的字母呢?26个这么多字母,一个个打会疯掉.所有咱们可以用一个小技巧使用for循环帮我们把26个字母自动搞出来,大家来瞅一眼把! 使用Java遍历2 ...

  8. 浅入javascript正则表达式的规则.

    今天在看jQuery源码的时候,到处都是正则的用法,一气之下就狠下心来.重新回顾了一下正则.下面是做的笔记.非常浅的入门. /* i:表示不区分大小写 g:表示可以全局配置 m:表示可以多行配置 */ ...

  9. 初识java——运算符和表达式以及注释

    java中有不同的运算符,并且在运算中有着优先级的排序计算,其中++和——的优先级最高,最先计算 运算符注意:1,增量和减量运算符++,——. int a=1++; int b=++1; 其中1++表 ...

  10. 多台或者集群环境下如何保证spring定时器只执行一个

    先说一下我们的系统, 在65和66上分别部署有weblogic节点,共计四个,在项目中我们的定时器会隔一段时间就从其它的五个系统中取数据,这时就出现了问题,本来取一次数据就可以的,现在重复执行了三次, ...