2013年12月16日

基于TCP的NAT子网穿透实验

摘要: 不得不说,在国内IP紧缺的现状下,NAT发挥了无比巨大的作用:它以把IP和端口重新分配的方式,满足了广大人民群众上网的强烈需求。但是对于个人服务器以及在内网中基于网络的嵌入式设备,却是个比较尴尬的事情:因为它把端口和IP进行了重新分配,外网客户端访问的时候很难知道server端的IP和监听端口,尤其是监听端口。这个时候,子网穿透技术就应运而生了。 这两天看了一些简单的子网穿透的基本原理,大多数都是UDP的。但是看完后觉得TCP实现起来更为简单,因此简单的写了一个测试程序实验了一下,结果还真行。下面是实现原理: 首先是搭建了一下网络模型,一个是在子网中的需要穿透的Server A,一个是在公网. 阅读全文

posted @ 2013-12-16 14:40 守夜者 阅读(13588) 评论(8) 推荐(0) 编辑

2013年8月12日

不同优化选项对ARM下C语言编译的影响

摘要: 我们知道在C语言编译时,有那么几个常用的优化编译选项,分别是-O0,-O1,-O2,-O3以及-Os。之前一直觉得既然是优化选项,顶多是优化一下逻辑,提高一些效率或者减少一下程序大小而已。很少会觉得它们会影响程序的最终结果。直到最近在ARM平台上发现一个程序里的一个bug,才觉得这些优化选项有时候也没那么智能。或者说针对ARM平台,还没有那么智能。 首先看这么一段程序,此程序是我将问题简单化的程序:#include#includeint main(){ char buffer[1024] = {0,1,2,3,4,5,6,7}; int iTest = 0x12345678; int ... 阅读全文

posted @ 2013-08-12 18:35 守夜者 阅读(4051) 评论(0) 推荐(1) 编辑

2012年8月16日

阻塞机制下的recv小结

摘要: recv是socket编程中最常用的函数之一,在阻塞状态的recv有时候会返回不同的值,而对于错误值也有相应的错误码,分别对应不同的状态,下面是我针对常见的几种网络状态的简单总结。 首先阻塞接收的recv有时候会返回0,这仅在socket被正常关闭时才会发生。而当拔掉设备网线的时候,recv并不会发生变化,仍然阻塞,如果在这个拔网线阶段,socket被关掉了,后果可能就是recv永久的阻塞了。所以一般对于阻塞的socket都会用setsockopt来设置socket的超时。 当超时时间到达后,recv会返回错误,也就是-1,而此时的错误码是EAGAIN或者EWOULDBLOCK,POSIX.. 阅读全文

posted @ 2012-08-16 22:05 守夜者 阅读(25150) 评论(4) 推荐(3) 编辑

2011年9月25日

实例分析用指针访问二维数组的几种方法

摘要: 之前对数组的概念一直没有理解透彻,只觉得数组名就是个常量指针而已,用法和基本的指针差不多。所以当我尝试用二级指针去访问二维数组时,就经常会出错。下面就是刚开始写的一个错误的程序:#include <stdio.h>int main(){ int iArray[2][3] = {{1,2,3},{4,5,6}}; int **pArray = NULL; pArray = iArray; printf("array[0][0] = %d\n", pArray[0][0]); printf("ar... 阅读全文

posted @ 2011-09-25 12:30 守夜者 阅读(18769) 评论(6) 推荐(3) 编辑

2011年9月13日

浅析linux下c程序堆栈分布

摘要: 我们知道c语言中的程序中的数据根据分布一般可以分为三种,一种是分布在数据段中的,一种是分布在栈上的,还有一种分布是堆上。全局变量往往都存放在数据段中,而函数中声明的变量一般都存放在栈上,而用malloc或者calloc分配出来的空间则是在堆上。但是我之前一直不知道这数据段、堆还有栈到底在内存上是怎样分布的,更不知道它们之间的距离是多少,也不会根据数据的指针来判断数据的类型。但是前些日子,为了跟踪一个数据莫名被修改的问题,终于对这堆栈的分布有了个形象的了解。 在《UNIX环境高级编程》中提到:对于x86处理器上的Linux,正文段从0x08048000单元开始,栈底则在0xC0000000之下. 阅读全文

posted @ 2011-09-13 21:10 守夜者 阅读(3291) 评论(2) 推荐(2) 编辑

2011年9月6日

gdb之小试牛刀

摘要: 在linux下编程的调试工具往往比较少,其中比较有名的就是gdb。而由于程序都是在ARM板子上跑,往往会由于资源不够,连gdb都无法运行。所以之前调试跟踪问题往往也只是用简单的printf来解决,都没怎么用过gdb。但是今天遇到了一个printf无法跟踪的问题,这时才想起来gdb。通过应用gdb,发现gdb功能真是强大,下面记录了一下我用到的命令。./gdb testprogram :表示用gdb去跑testprogram这个程序,由于我的gdb程序是在当前目录下,所以前面加了./ 如果gdb在系统环境变量的目录中(比如/bin)的话就直接运行gdb testprogram就行。ps:有时候. 阅读全文

posted @ 2011-09-06 22:20 守夜者 阅读(912) 评论(0) 推荐(0) 编辑

2011年7月3日

简单分析一下socket中的bind

摘要: 在最开始接触bind的时候,只是在写基于tcp的server端的时候,知道在listen之前需要先bind一下,用来确保socket能在某个固定的端口监听。而bind的时候,函数参数中的端口填自己将要绑定的端口就行;而IP地址,需要填本机的IP,但是也可以用一个宏INADDR_ANY代替,用这个宏就可以不用查找本机的IP,它就可以代替本机的IP。当时只觉得这个INADDR_ANY比较神奇,但是由于当时觉得用起来很方便,也没出啥问题,也就没有再深究。 但是最近在做RTSP服务器的时候,有种特殊的应用,导致我不得不对bind这个函数仔细地看一下。 我们知道无论是UDP还是TCP,socke... 阅读全文

posted @ 2011-07-03 13:17 守夜者 阅读(75483) 评论(13) 推荐(6) 编辑

2011年4月10日

简析LIVE555中的延时队列

摘要: 最近在看LIVE555的源码,感觉其中的延时队列写的不错,于是就总结一下。 首先描述一下LIVE555中的延时队列的设计理念。首先,如下图,A,B,C分别为时间轴上的三个事件点,而head表示当前时间点。 假如我们要描述一个事件发生的时间,可以有两种方法:一种方法直接描述事件发生的绝对时间;另一种方法则是可以描述和另一事件发生的相对时间。而LIVE555中采用的就是后者。在LIVE555中,首先将所有的事件点以发生时间的先后进行排序,然后每个事件对应的时间都是相对于前一事件发生的时间差。比如B事件中存储的时间就是A事件触发后,再去触发B事件所需要的时间。这样,我们每次去查询这个队列中是否有事. 阅读全文

posted @ 2011-04-10 10:33 守夜者 阅读(3741) 评论(1) 推荐(0) 编辑

2011年3月19日

指针类型对指针做差的影响

摘要: 之前知道指针变量其实存放的就是数据在存储空间存储的地址,而地址在32位机上往往都是32位数据,感觉都是一样的,与所指向的数据的类型关系不大。所以一直觉得指针类型的唯一作用,就是提高程序可读性,防止我们滥用指针。至于指针做差的返回值应该就是地址的差值。但是最近有一次对指针进行做差的时候,无意中发现其实并没有这么简单。源代码如下:#include<stdio.h>int main(){ int *p1 = (int *)0; int *p2 = (int *)4; int result; printf("p1 = %d, p2 = %d\n... 阅读全文

posted @ 2011-03-19 20:11 守夜者 阅读(1131) 评论(6) 推荐(0) 编辑

2011年3月13日

它被定义了,但它却被定义为未定义——有趣的宏定义

摘要: 前些日子为了弄清楚宏定义写了个小程序,忽然发现将标识符定义为空和将标识符定义为未定义完全是两码事……然后发现原来宏定义中还有一种状态叫“未定义”。下面就是那个小程序以及简单的分析,然后通过这个程序可以充分体验一下这个“未定义”的状态,体验一下什么叫“它被定义了,但它却被定义为未定义”。程序源码:#include<stdio.h>int main(){#if (A == B) printf("define A = B\n");#elif (A == C) printf("define A = C\n");#else printf("n 阅读全文

posted @ 2011-03-13 11:09 守夜者 阅读(2978) 评论(2) 推荐(0) 编辑

导航