已阅读5页,还剩224页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C/C+实战之内存管理2002-10-17C/C+实战之内存管理 欢迎大家来到这片大多数程序员都心有余悸的雷区。本世纪伟大的比尔盖茨曾经失言: 640K ought to be enough for everybody - Bill Gates 1981相信程序员们都经常要编写一些关于内存分配和使用的程序,而且都有过那种生不如死的感觉(当然我是指那种调试程序的感觉了,可能夸张了些!)常见的内存分配和使用错误1) 内存的申请和分配并没有成功,但程序员却使用了它。一些新手经常会犯这种错误,他们并不会留意到内存没有分配成功。判断指针的值是否为NULL可以有效地避免这种错误。2) 内存的分配已经成功,但是却没有进行初始化就直接使用它了。首先是观念上的问题,很多人都没有在使用指针前要初始化这样的习惯,然而这个习惯却是很重要的,希望大家一定要强迫自己养成。第二就是主观地认为自己申请的内存的缺省值为0,这样想是没有什么道理的,内存分配后的值是不确定的。3) 上面的两种工作都已经做好了(已经成功申请并初始化完成),但是操作时却越界了。4) 申请了内存,使用完了却忘记了释放,导致内存泄露。这样的错误可以形容为一个恶性的肿瘤,它不会马上要你的命,但是它会慢慢地吞噬你的系统资源,直到你的程序彻底完蛋。5) 你很小心地释放了内存,但是却又使用了它。由于程序很复杂或者调用顺序出错,这样可能导致出现上面的错误。指针-一把伟大的双刃剑我真的非常佩服发明指针的人,他简直太伟大了。能使用如此简洁地方法将复杂的内存结构描述的如此清楚,这本身就是一种伟大的成就。但是,指针之于程序员如同武器之于士兵,用好了可以威力无比,用不好则害人害己。我先说说指针和数组的区别。数组名对应着一块内存,它的地址、容量在其生命周期中是不可变的,只有数组内容是可变的。指针可随时指向任何类型的内存,它的特点就是“变”。指针远比数组灵活,但也更危险。数组名是不能直接进行赋值和比较的。如果你向要将数组a赋值给数组b,不能直接用赋值语句b = a ,这样会令编译器产生错误的。必须使用标准的库函数strcpy来进行赋值。相同地,要比较a和b的内容是否相同,不能使用普通的逻辑判断if(b=a),也要应用库函数strcmp来判断。/数组char a = “hello”;char b100;strcpy(b, a); / b = a is wrongif (strcmp(b, a) = 0) /if (b = a) is wrongcoutbendl;/指针int len = strlen(a);char *p = (char *)malloc(sizeof(char)*(len+1);strcpy(p, a);if (strcmp(p, a) = 0)coutp*pmf)(str, “abc”); /函数的调用方法为:dispatcher(a, pmf); / .* 方式dispatcher(&a, pmf); / -* 方式高级使用技巧以上是成员函数的基本知识。现在介绍它的高级使用技巧。成员指针数组在下例,声明了一个含有二个成员指针的数组,并分配类的成员函数地址给成员指针:PMA pmf2= &A:strcpy, &A:strcat;这样的数组在菜单驱动应用中很有用。选择菜单项后,应用将调用相应的回叫函数,如下所示:enum MENU_OPTIONS COPY, CONCAT ;int main() MENU_OPTIONS option; char str4; /从外部资源读取选项switch (option) case COPY: (pa-*pmfCOPY)(str, “abc”); break; case CONCAT: (pa-*pmfCONCAT)(str, “abc”); break; / Const 类型的成员函数成员指针的类型应该与成员函数类型一致。上面例子中的pmf 可以指向A的任意函数,只要该函数不是const类型。如下所示,如果将touppercase()的地址分配给pmf,将导致编译出错,因为touppercase() 的类型是const。Class A public: void strpcy(char *, const char *); void strcat(char *, const char *); void touppercase(char *, const char*) const; ; pmf=&A:touppercase; /出错,类型不匹配/解决的方法是声明一个const类型的成员指针:void (A:pcmf)(char *, const char *) const; pcmf=&A:touppercase; / 现在可以了有些差劲的编译器允许一个非const类型的成员指针指向const类型的成员函数。这在标准C+是不允许的。结语可能有点费解:成员指针不是真正的指针。传统意义上的指针是一个整数,保存指向某个变量或函数的地址。成员指针则是一个复合数据结构,包含有若干个数据成员。成员指针的这个复杂性使得入门比较困难。然而,一旦掌握了它的语法,就能感到它是在事件驱动和多线程应用中调用回叫函数必不可少的工具。原作者: 未够意思 来 源: 网上 const使用方法探讨2002-8-20关于C+中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,现将本人的一些体会总结如下,期望对大家有所帮助:一 const基础如果const关键字不涉及到指针,我们很好理解,下面是涉及到指针的情况:int b = 500;const int* a = &b; 1int const *a = &b; 2int* const a = &b; 3const int* const a = &b; 4如果你能区分出上述四种情况,那么,恭喜你,你已经迈出了可喜的一步。不知道,也没关系,我们可以参考Effective c+Item21上的做法,如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。因此,1和2的情况相同,都是指针所指向的内容为常量(const放在变量声明符的位置无关),这种情况下不允许对内容进行更改操作,如不能*a = 3 ;3为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如a+是错误的;4为指针本身和指向的内容均为常量。另外const 的一些强大的功能在于它在函数声明中的应用。在一个函数声明中,const 可以修饰函数的返回值,或某个参数;对于成员函数,还可以修饰是整个函数。有如下几种情况,以下会逐渐的说明用法:A& operator=(const A& a);void fun0(const A* a ); void fun1( ) const; / fun1( ) 为类成员函数const A fun2( ); 二 const的初始化先看一下const变量初始化的情况1) 非指针const常量初始化的情况:A b;const A a = b;2) 指针(引用)const常量初始化的情况:A* d = new A();const A* c = d;或者:const A* c = new A();引用:A f;const A& e = f; / 这样作e只能访问声明为const的函数,而不能访问一般的成员函数;思考1: 以下的这种赋值方法正确吗?const A* c=new A();A* e = c;思考2: 以下的这种赋值方法正确吗?A* const c = new A();A* b = c;三 作为参数和返回值的const修饰符其实,不论是参数还是返回值,道理都是一样的,参数传入时候和函数返回的时候,初始化const变量1 修饰参数的const,如 void fun0(const A* a ); void fun1(const A& a);调用函数的时候,用相应的变量初始化const常量,则在函数体中,按照const所修饰的部分进行常量化,如形参为const A* a,则不能对传递进来的指针的内容进行改变,保护了原指针所指向的内容;如形参为const A& a,则不能对传递进来的引用对象进行改变,保护了原对象的属性。注意:参数const通常用于参数为指针或引用的情况;2 修饰返回值的const,如const A fun2( ); const A* fun3( );这样声明了返回值后,const按照“修饰原则”进行修饰,起到相应的保护作用。const Rational operator*(const Rational& lhs, const Rational& rhs)return Rational(lhs.numerator() * rhs.numerator(),lhs.denominator() * rhs.denominator();返回值用const修饰可以防止允许这样的操作发生:Rational a,b;Radional c;(a*b) = c;一般用const修饰返回值为对象本身(非引用和指针)的情况多用于二目操作符重载函数并产生新对象的时候。总结 一般情况下,函数的返回值为某个对象时,如果将其声明为const时,多用于操作符的重载。通常,不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的情况。原因如下:如果返回值为某个对象为const(const A test = A 实例)或某个对象的引用为const(const A& test = A实例) ,则返回值具有const属性,则返回实例只能访问类A中的公有(保护)数据成员和const成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到。思考3: 这样定义赋值操作符重载函数可以吗?const A& operator=(const A& a);四 类成员函数中const的使用一般放在函数体后,形如:void fun() const;如果一个成员函数的不会修改数据成员,那么最好将其声明为const,因为const成员函数中不允许对数据成员进行修改,如果修改,编译器将报错,这大大提高了程序的健壮性。五 使用const的一些建议1 要大胆的使用const,这将给你带来无尽的益处,但前提是你必须搞清楚原委;2 要避免最一般的赋值操作错误,如将const变量赋值,具体可见思考题;3 在参数中使用const应该使用引用或指针,而不是一般的对象实例,原因同上;4 const在成员函数中的三种用法(参数、返回值、函数)要很好的使用;5 不要轻易的将函数的返回值类型定为const;6 除了重载操作符外一般不要将返回值类型定为对某个对象的const引用;本人水平有限,欢迎批评指正,可以联系 kang_思考题答案1 这种方法不正确,因为声明指针的目的是为了对其指向的内容进行改变,而声明的指针e指向的是一个常量,所以不正确;2 这种方法正确,因为声明指针所指向的内容可变;3 这种做法不正确;在const A:operator=(const A& a)中,参数列表中的const的用法正确,而当这样连续赋值的时侯,问题就出现了:A a,b,c:(a=b)=c;因为a.operator=(b)的返回值是对a的const引用,不能再将c赋值给const常量。原作者: kangcau 来 源: CSDN C代码风格2002-8-19C代码风格 人们看到的最好的作家有时并不理会修饰学的规则。 还好,当他们这样做虽然付出了违反常规的代价, 读者还经常能从句子中发现某些具有补偿性的价值, 除非作者也明确其做法的意思,否则最好还是按规矩做 William Strunk AND E.B White 风格的要素 作者:丁春秋 (如果您要转载这篇文章,请不要删减里面任何内容,珍惜劳动者的成果) 这是我的第一篇技术贴,也是我对代码风格的一点想法。一点点感悟 如果我的认识有错误,还请大家不吝赐教。 我们(C程序员,渴望成为C程序员的人)全为着一个共同的目标 而前进钻研C语言的最深魅力。 我们感谢得C语言的缔造者Dennis M.Ritchie让我们可以使用这样 一个神奇的语言。他是所有C程序员心中的圣人。 我常被问及C语言的各种问题,但是很少人跟我讨论过代码风格。 一次我不经意的问一个硕士生,他的回答让我汗颜。 ME:“你的代码风格不是太好。” HE:“那你说说我的代码风格是怎么个不好?” ME:“” HE:“代码最重要的是性能,风格是其次” 最后一句话让我最起码沉默了十分钟。试问,没有风格哪来性能? 好的风格对于好的程序具有关键性的作用; 请你给下面两个程序代码捉虫。 /*例程1*/ #include int main() int Number10,Numadd_One,l,Numadd_Tow; for(Numadd_One=0;Numadd_One10;Numadd_One+) scanf(%d,&NumberNumadd_One); for(Numadd_One=0;Numadd_One10;Numadd_One+) for(Numadd_Tow=0;Numadd_TowNumberNumadd_Tow+1) l=NumberNumadd_Tow;NumberNumadd_Tow = NumberNumadd_Tow+1;NumberNumadd_Tow+1=j; /*例程2*/ #include #define MAX 10 int main() int numberMAX; int n; int j; int temp; for( n = 0 ; n MAX ; n+ ) scanf( %d,&numbern ); for( n = 0 ; n MAX ; n+ ) for( j = 0 ; j numberj + 1 ) temp = numberj; numberl = numberj + 1; numberj + 1 = temp; 在这里,有着代码风格的代码好处就明显现露出来了。别告诉 我你觉得第一个例子的风格够好 代码应该是清楚的简单的具有直截了当的逻辑,自然的表达式。 而不是一篇乱七八糟的作文稿。 对,没错,第一个例子的变量申明确可以省下不少时间和占用 空间,但是你忘记刚才捉虫的经历了吗?如此的代码格式会让你 的同事抓狂。 int PlaseInput,NumberIput,l,KillerNumber; 在中间的l不经意就会没看见它; 如果分开写的话会让你和你的同事看的更清楚,对变量名称更了解; Number10,Numadd_One,Numadd_Tow 等等,这样的变量名字看起来实在是太罗嗦。 名字是什么?一个名字是用来标识函数或变量的对象。 要带着一些有用途的信息,一个名字应该是非形式的,简单的, 容易记的。一个变量的作用越大,它名字要携带的信息就该更多。 全局变量应该更加注意些。 作为非明文规定,局部变量应用小写字母, 全局变量应大写开头字母; 常量名应全大写; 函数名应该写为动作性的; 结构名应该带有整体性; 有很多人总是鼓励变量名写的够长,容易携带信息; 那是鬼话,清晰都是随着简洁而来的。 表达式的缩进状态是非常重要的,把刚才的例程1和例程2对比一下 就有明显的结果。表达式的缩进效果应该可以你可以瞬间毫不费力的 看完而不会觉得象一块压缩饼干一样积压在一起。而且还要求可以 看到相当清晰的结构性,没有一点视觉上的障碍。 表达式应该有够自然,应该可以让你大声的读出来。 如果遇到了优先级的判断时,并不确定哪个先执行或哪个后执行时 加上括号强调她的优先级,这没有错,也并不羞耻。不要害怕谁说 你连优先级都没背清楚 有时候我们尽力把创造力发挥在简短的代码上,从而寻求最简短的 解决办法,但是有时候这技巧用错了地方,我们写代码的目的是写出 清晰易懂的代码,而不是炫耀自己的创造力。 看看这代码到底想要做些什么 subkey = subkey (bitoff - ( (bitoff 3) 3 ); 记住,清晰性并不等于简短,这里是互相矛盾的。 有时候短的代码更容易说明一切,也有时候短的代码也搞混一切。 可怕的魔术数字 什么是可怕的魔术数字? 看下列代码 for( i = 3 ; i + 3 / 4 ? i+ : i- ; n+ , p+ ) if( p 200 ) p = p / 3 - i / 5; 这个循环代码实在是有够可怕的,但是可怕的并不是这个循环。 而是这里面的数字,她们在不停的变化。这不是最糟糕的; 糟糕的是你将在30000行的程序中更改这些数字 但是假如你先知性的做了准备将这些幻数定义为常量或枚举, 那你的情况就不会这么糟糕了。 也有人说把数字定义为常数而不是宏,这是有弊有利的。 大家自己权衡情况。 你写过注释吗?你为自己程序做过文档吗? 注释是自己程序的好向导,文档是自己的好帮手。 不要以为程序是自己写的不可能忘记,那你就大错他错了。 我记得我做新手的时候开发项目,是老手带领我们几个新手来做。 我负责的那部分模块相当简单,我很快就草草了事了。 然后也没管太多,谁知道程序演示版被客户返工了。 我和另外两个兄弟负责的模块有问题,但离交工的日子不远了, 我和另外两个兄弟连夜赶工,但是我发现我自己写的代码竟然有好多 功能连我自己都不清楚了。我当时真恨我注释和文档没写清楚。 要不然就没有那么尴尬的情况出现了。后来把这个模块重新写了一遍 调了N遍,那最后一天终于通过客户那一关了。 整个人累的跟只死狗一样。 无论是新手还是老手,都应该写好注释和文档, 必要的时候文档应当记录实现某些功能的代码方案, 写注释的风格有N多种,我这里就不说了。 总之找到一种适合自己的风格,然后坚持下去。 让这种风格成为习惯,但是这风格一定要让其他人接受。 尽量和其他人保持风格的一致性,你看别人的代码轻松。 别人看你的代码也同样轻松。 另外如何鉴定自己的风格? 如果你找到一种自己喜欢的风格,不要问,使用她吧。等你按照这种风格写过 100行的程序之后,叫来几个懂计算机语言的朋友,让她们来感觉这些英文代码 和你以前写的是否看起来更舒服。 最后请记住,一个风格好的程序比那些风格差的程序更容易读,也更容易修改。 原作者: 丁春秋 来 源: 网上 C语言编程来使网卡工作在混杂模式2002-10-162001-04-01秋天的树 一 前言 SNIFF真是一个古老的话题,关于在网络上采用SNIFF来获取敏感信息已经不是什么 新鲜事,也不乏很多成功的案例,那么,SNIFF究竟是什么呢? SNIFF就是嗅探器,就是 窃听器,SNIFF静悄悄的工作在网络的底层,把你的秘密全部记录下来。看过威尔史密斯 演的全民公敌吗?SNIFF就象里面精巧的窃听器一样,让你防不胜防。 SNIFF可以是软件,也可以是硬件,既然是软件那就要分平台,有WINDOWS下的、UNXI 下的等,硬件的SNIFF称为网络分析仪,反正不管硬件软件,目标只有一个,就是获取在网 络上传输的各种信息。本文仅仅介绍软件的SNIFF。 当你舒适的坐在家里,惬意的享受网络给你带来的便利,收取你的EMAIL,购买你喜欢 的物品的时候,你是否会想到你的朋友给你的信件,你的信用卡帐号变成了一个又一个的 信息包在网络上不停的传送着,你是否曾经这些信息包会通过网络流入别人的机器呢?你 的担忧不是没有道理的,因为SNIFF可以让你的担忧变成实实在在的危险。就好象一个人躲 在你身后偷看一样。 二 网络基础知识 “网络基础知识”,是不是听起来有点跑题了?虽然听起来这和我们要谈的SNIFF没什么 关系,可是还是要说一说的,万丈高楼平地起,如果连地基都没打好,怎么盖楼?!如果你 对网络还不是十分清楚的话,最好能静下心来好好看看,要知道,这是基础的基础,在这里 我只是简单的说一下,免得到时候有人迷糊,详细的最好能够自己去找书看看。 (1)TCP/IP体系结构 开放系统互连(OSI)模型将网络划分为七层模型,分别用以在各层上实现不同的功能, 这七层分别为:应用层、表示层、会话层、传输层、网络层、数据链路层及物理层。而TCP/IP 体系也同样遵循这七层标准,只不过在某些OSI功能上进行了压缩,将表示层及会话层合并入 应用层中,所以实际上我们打交道的TCP/IP仅仅有5层而已,网络上的分层结构决定了在各层 上的协议分布及功能实现,从而决定了各层上网络设备的使用。实际上很多成功的系统都是基 于OSI模型的,如:如帧中继、ATM、ISDN等。 TCP/IP的网络体系结构(部分) - | SMTP | DNS | HTTP | FTP | TELNET| 应用层 - | TCP | UDP | 传输层 - | IP | ICMP | ARP RARP | 网络层 - | IEEE 802 以太网 SLIP/PPP PDN etc| 数据链路层 - | 网卡 电缆 双绞线 etc | 物理层 - 从上面的图中我们可以看出,第一层物理层和第二层数据链路层是TCP/IP的基础,而 TCP/IP本身并不十分关心低层,因为处在数据链路层的网络设备驱动程序将上层的协议和 实际的物理接口隔离开来。网络设备驱动程序位于介质访问子层(MAC)。 (2)网络上的设备 中继器:中继器的主要功能是终结一个网段的信号并在另一个网段再生该信号,一句话, 就是简单的放大而已,工作在物理层上。 网 桥:网桥使用MAC物理地址实现中继功能,可以用来分隔网段或连接部分异种网络,工 作在数据链路层。 路由器:路由器使用网络层地址(IP,X.121,E.164等),主要负责数据包的路由寻径,也能 处理物理层和数据链路层上的工作。 网 关:主要工作在网络第四层以上,主要实现收敛功能及协议转换,不过很多时候网关都 被用来描述任何网络互连设备。 (3)TCP/IP与以太网 以太网和TCP/IP可以说是相互相成的,可以说两者的关系几乎是密不可分,以太网在 一二层提供物理上的连线,而TCP/IP工作在上层,使用32位的IP地址,以太网则使用48位 的MAC地址,两者间使用ARP和RARP协议进行相互转换。从我们上面TCP/IP的模型图中可以 清楚的看到两者的关系。 载波监听/冲突检测(CSMA/CD)技术被普遍的使用在以太网中,所谓载波监听是指在以 太网中的每个站点都具有同等的权利,在传输自己的数据时,首先监听信道是否空闲,如 果空闲,就传输自己的数据,如果信道被占用,就等待信道空闲。而冲突检测则是为了防 止发生两个站点同时监测到网络没有被使用时而产生冲突。以太网采用广播机制,所有与 网络连接的工作站都可以看到网络上传递的数据。 为了加深你的理解,我们来看看下面的图,一个典型的在以太网中客户与服务器使用 TCP/IP协议的通信。 用户进程 FTP客户 FTP服务器 应用层 | | 内核中的协议栈 TCP TCP 传输层 | | 内核中的协议栈 IP IP 网络层 | | 以太网驱动程序 以太网驱动程序 数据链路层 - 以太网 ?唆唆了这么多,有人烦了吧?相信我,这是基础的基础,可以说是说得是很简单拉, 如果需要,拿出个几十万字来说上面的内容,我想也不嫌多,好了,让我们进入下一节, sniff的原理。 三 SNIFF的原理 要知道在以太网中,所有的通讯都是广播的,也就是说通常在同一个网段的所有网络接 口都可以访问在物理媒体上传输的所有数据,而每一个网络接口都有一个唯一的硬件地址, 这个硬件地址也就是网卡的MAC地址,大多数系统使用48比特的地址,这个地址用来表示网 络中的每一个设备,一般来说每一块网卡上的MFC地址都是不同的,每个网卡厂家得到一段 地址,然后用这段地址分配给其生产的每个网卡一个地址。在硬件地址和IP地址间使用ARP 和RARP协议进行相互转换。 在正常的情况下,一个网络接口应该只响应这样的两种数据帧: 1.与自己硬件地址相匹配的数据帧。 2.发向所有机器的广播数据帧。 在一个实际的系统中,数据的收发是由网卡来完成的,网卡接收到传输来的数据,网卡 内的单片程序接收数据帧的目的MAC地址,根据计算机上的网卡驱动程序设置的接收模式判 断该不该接收,认为该接收就接收后产生中断信号通知CPU,认为不该接收就丢掉不管,所 以不该接收的数据网卡就截断了,计算机根本就不知道。CPU得到中断信号产生中断,操作 系统就根据网卡的驱动程序设置的网卡中断程序地址调用驱动程序接收数据,驱动程序接收 数据后放入信号堆栈让操作系统处理。而对于网卡来说一般有四种接收模式: 广播方式:该模式下的网卡能够接收网络中的广播信息。 组播方式:设置在该模式下的网卡能够接收组播数据。 直接方式:在这种模式下,只有目的网卡才能接收该数据。 混杂模式:在这种模式下的网卡能够接收一切通过它的数据,而不管该数据是否是传给它的。 好了,现在我们总结一下,首先,我们知道了在以太网中是基于广播方式传送数据的,也 就是说,所有的物理信号都要经过我的机器,再次,网卡可以置于一种模式叫混杂模式 (promiscuous),在这种模式下工作的网卡能够接收到一切通过它的数据,而不管实际上数 据的目的地址是不是他。这实际上就是我们SNIFF工作的基本原理:让网卡接收一切他所能接 收的数据。 (图一) 我们来看一个简单的例子,如图一所示,机器A、B、C与集线器HUB相连接,集线器HUB通 过路由器Router访问外部网络。这是一个很简单也很常见的情况,比如说在公司大楼里,我 所在的网络部办公室里的几台机器通过集线器连接,而网络部、开发部、市场部也是同样如 此,几个部门的集线器通过路由器连接。还是回到我们的图一上来,值得注意的一点是机器 A、B、C使用一个普通的HUB连接的,不是用SWITCH,也不是用ROUTER,使用SWITCH和ROUTER 的情况要比这复杂得多。 我们假设一下机器A上的管理员为了维护机器C,使用了一个FTP命令向机器C进行远程登陆, 那么在这个用HUB连接的网络里数据走向过程是这样的。首先机器A上的管理员输入的登陆机 器C的FTP口令经过应用层FTP协议、传输层TCP协议、网络层IP协议、数据链路层上的以太网 驱动程序一层一层的包裹,最后送到了物理层,我们的网线上。接下来数据帧送到了HUB上, 现在由HUB向每一个接点广播由机器A发出的数据帧,机器B接收到由HUB广播发出的数据帧, 并检查在数据帧中的地址是否和自己的地址相匹配,发现不是发向自己的后把这数据帧丢弃, 不予理睬。而机器C也接收到了数据帧,并在比较之后发现是发现自己的,接下来他就对这数 据帧进行分析处理。 在上面这个简单的例子中,机器B上的管理员如果很好奇,他很想知道究竟登陆机器C上FTP 口令是什么?那么他要做的很简单,仅仅需要把自己机器上的网卡置于混杂模式,并对接收到 的数据帧进行分析,从而找到包含在数据帧中的口令信息。 四 做一个自己的sniff 在上一节里,我们已经知道了SNIFF的基本原理是怎么一回事,这一节我们来亲自动手做一个 自己的sniff,毕竟,用程序代码来说话比什么都要来得真实,也容易加深理解。 回头想一想我们上面说的原理,我们要做的事情有几件: 1. 把网卡置于混杂模式。 2. 捕获数据包。 3. 分析数据包。 注:下面的源代码取至Chad Renfro的 一文中 /*Tcp_sniff_2.c*/ 1.#include 2.#include 3.#include 4.#include 5.#include 6.#include 7.#include 8.#include 9.#include headers.h #define INTERFACE eth0 /*Prototype area*/ 10.int Open_Raw_Socket(void); 11.int Set_Promisc(char *interface, int sock); 12.int main() 13.int sock, bytes_recieved, fromlen; 14.char buffer65535; 15.struct sockaddr_in from; 16.struct ip *ip; 17.struct tcp *tcp; 18.sock = Open_Raw_Socket(); 19. Set_Promisc(INTERFACE, sock); 20. while(1) 22. 23. fromlen = sizeof from; 24. bytes_recieved = recvfrom(sock, buffer, sizeof buffer, 0, (struct sockaddr *)&from, &fromlen); 25. printf(nBytes received : %5dn,bytes_recieved); 26. printf(Source address : %sn,inet_ntoa(from.sin_addr); 27. ip = (struct ip *)buffer; /*See if this is a TCP packet*/ 28. if(ip-ip_protocol = 6) 29. printf(IP header length : %dn,ip-ip_length); 30. printf(Protocol : %dn,ip-ip_protocol); 31. tcp = (struct tcp *)(buffer + (4*ip-ip_length); 32. printf(Source port : %dn,ntohs(tcp-tcp_source_port); 33. printf(Dest port : %dn,ntohs(tcp-tcp_dest_port); 34. 35. 36. 37.int Open_Raw_Socket() 38. int sock; 39. if(sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP) 0) /*Then the socket was not created properly and must die*/ 40. perror(The raw socket was not created); 41. exit(0); 42. ; 43. return(sock); 44. 45.int Set_Promisc(char *interface, int sock ) 46. struct ifreq ifr; 47. strncpy(ifr.ifr_name, interface,strnlen(interface)+1); 48. if(ioctl(sock, SIOCGIFFLAGS, &ifr) = -1) /*Could not retrieve flags for the interface*/ 49. perror(Could not retrive flags for the interface); 50. exit(0); 51. 52. printf(The interface is : %sn, interface); 53. perror(Retrieved flags from interface successfully); 54. ifr.ifr_flags |= IFF_PROMISC; 55. if (ioctl (sock, SIOCSIFFLAGS, &ifr) = -1 ) /*Could not set the flags on the interface */ 56. perror(Could not set the PROMISC flag:); 57. exit(0); 58. 59. printf(Setting interface : %s : to promisc, interface); 60. return(0); 61. /*EOF*/ 上面这段程序中有很详细的注解,不过我想还是有
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2027年河北省历史高考高考仿真卷(含答案+解析)
- 靶向训练 2027年河南省政治高三鲁教版模拟演练卷(含答案+解析)
- 2027年天津市语文高三考前加分卷(含答案+解析)
- 2027年新高考II卷政治高考三轮回归基础卷(含答案+解析)
- 求职者短期住宿协议范本求职公寓租赁合同二篇
- 2026年中国传统工艺品市场调查研究报告
- 2026新型结合剂对粘土质耐火砖高温蠕变性能影响机制深度研究报告
- 2026综合类-中医妇科学主治医师-中医妇科学-月经病历年真题摘选带答案详解
- 2026经济师-中级经济师-中级经济师人力资源管理历年参考题库含答案详解
- 2026福建省机关事业单位工勤人员技能等级考试(矫形器制作装配工)历年参考题库含答案详解
- 2026年广东省国家工作人员学法用法考试通-用题库及答案
- 2026年辽宁省大连市辅警人员招聘考试试题及答案
- 2026新人教版二年级上册小学数学教学计划附教学进度表教案
- 金蝶云星空总账初始化操作手册
- 新版2026秋新人教版五年级上册语文全册教案合集
- 新苏教版科学五年级上册 3.9《弹力》教学课件
- 水利水电工程单元工程施工质量检验表与验收表(SLT631.5-2025)
- 宅基地制度改革试点档案
- 2024届上海市普通高中物理高二第一学期期末学业质量监测试题含解析
- YB/T 319-1997冶金用锰矿石
- GB/T 3730.1-2001汽车和挂车类型的术语和定义
评论
0/150
提交评论