登录社区:用户名: 密码: 忘记密码 网页功能:加入收藏 设为首页 网站搜索  

文档

下载

图书

论坛

安全

源码

硬件

游戏
首页 信息 空间 VB VC Delphi Java Flash 补丁 控件 安全 黑客 电子书 笔记本 手机 MP3 杀毒 QQ群 产品库 分类信息 编程网站
  立华软件园 - 安全技术中心 - 技术文档 - 入门基础 技术文章 | 相关下载 | 电子图书 | 攻防录像 | 安全网站 | 在线论坛 | QQ群组 | 搜索   
 安全技术技术文档
  · 安全配制
  · 工具介绍
  · 黑客教学
  · 防火墙
  · 漏洞分析
  · 破解专题
  · 黑客编程
  · 入侵检测
 安全技术工具下载
  · 扫描工具
  · 攻击程序
  · 后门木马
  · 拒绝服务
  · 口令破解
  · 代理程序
  · 防火墙
  · 加密解密
  · 入侵检测
  · 攻防演示
 安全技术论坛
  · 安全配制
  · 工具介绍
  · 防火墙
  · 黑客入侵
  · 漏洞检测
  · 破解方法
 其他安全技术资源
  · 攻防演示动画
  · 电子图书
  · QQ群组讨论区
  · 其他网站资源
最新招聘信息

C语言基本功教程系列(5) - 文件, Socket 和 其它
发表日期:2007-03-28作者:[转贴] 出处:  

 这个系列的最后一章了,基本上这篇里边拿不准的,或者记得不太清楚的,以及很确定的结论,都在网上或者书里找到了依据。如果大家不同意文章里的论点,拿砖头拍我或者拍原作者都可以。

今天的主题是文件访问,Socket,和其他一些值得注意的内容。文件和Socket比较类似,都是在说IO访问,不过在操作系统级别上的实现有很大不同。 IO访问无论从什么角度讲,都是计算机系统里最慢的操作。特别是在游戏制作中,动不动就几百兆的动态或者静态数据,贴图纹理,和各种音响音乐等。要一次性把这些所有的数据读到内存中是不大可能的,所以在游戏进行过程中要不短的从硬盘或者光驱里读文件。 如何能够最小化这个瓶颈, 是值得注意的问题。先从文件说起吧。

===================文件==================
C语言里,正常的文件操作一般是3步。
fp = fopen(XXXX,XXX);
读写操作....
fclose(fp);

首先要注意的是,fopen里边要用binary mode打开文件,不要用ASCII mode. 很多人在处理文本类型的文件时候,喜欢用 ASCII mode,然后用fgets一行一行的读。实际上ASCII mode无论如何操作,都是非常慢的,而且fgets函数更加的慢 [1]。所以即使是文本文件,也要用binary mode打开,一次读入一大块近来,慢慢处理。

其次需要注意的是,每一次读取文件的时候,硬盘都会对磁头进行重新定位和寻址。 这点会根据操作系统的不同而不同,总的来说windows XP要比  windows2000好点,但是也只是在系统文件方面 [2]。 因此每次读取的内容越多,平均效率就越高。同时操作系统提供磁盘缓存,当你写如磁盘的时候,只要不用fflush和fclose,数据在短时间内还是在内存中的,如果这时候再读出来写如的内容,也非常快。读写文件的时候不要用C++的流。写文件一次最好写不小于4k的数据, 而且最好对文件结构有效的安排,进行连续的访问(不要频繁使用fseek)[3]. 这些都有助于提高文件的访问速度。

最后,如上文中提到的,每次使用fclose和 fflush的时候,都会强迫文件从缓存中写如到磁盘里。这个过程极其缓慢而且耗费时间,所以不在必要的时候,不要使用fclose和fflush. 如果一个文件读写完毕,而你又不确定是否短时间内会用到它,那就不要用fclose.你可以专门写一个类,管理这写文件的指针。对于经常会进行操作的文件,比如大地图的texture文件等,fopen一次就ok了,直到游戏结束再fclose


===================SOCKET==================
SOCKET虽然也是IO访问,要比文件快多了。但是在recv的时候,还是一次读的越多越好。这样效率更高。下面说一些SOCKET编程的技巧。

1.  使用异步socket (asynchronous IO). 在网络程序设计中,又2种处理方式,第一种是对每一个连接请求,都使用一个线程或者进程,第2种是使用一个线程同时使用异步IO. 第一种方式虽然程序设计上简单,但是创立进程的时候一般会有一些时间用在建立context上,进程间的转换和 mutex等也需要浪费很多CPU资源,总体来说不如异步 IO 有效率 [4]。 

2. 如果必须要使用多线程,可以考虑事先就创建好该线程,然后在需要的时候,把socket发过去就行了[4]。

3. 在处理 UDP协议的时候,需要注意的是,UDP和TCP不一样。UDP没有control flow,如果接收端的buffer满掉了,再来的UDP包都会被drop掉。所以在处理UDP协议的时候,一般需要专门一个线程读UDP包,防止过多的数据包丢失。

4.  最后,网络数据包多大合适? 这个很难说。对于UDP来说,小包是不划算的. 我们通常用的Ethernet(也就是LAN),在第2层 Data link layer,最大的frame size 是1500 bytes,刨除最20 Bytes(最少)的IP头,8 bytes的 UDP头,所有最大的UDP包可以包含 1472个bytes。要是考虑IP包有可能会有附加头信息,一般1400就比较合适。但是如果有些老版本 router不地道,对你的UDP包分片的话,就比较惨了。能保证不分片的UDP包大小是513个byte左右 [5],不过毕竟现在这种老的 Router很少了,1400字节大小的UDP包还是比较安全的。对于TCP来说,因为是stream protocol,不用考虑包的大小。但是TCP 有个缺点,就是如果你一次发送很多很多数据,那么TCP的速度会一会快,一会慢(见[4]中的关于video streaming的介绍)。所以,需要程序调节,匀速发送数据。

====================其他===================
其他一些程序设计上的东西,很多可以参见 [6]

1. 能用UINT的地方就用UINT,因为很多是UINT最快,而且UINT的除法要比int快。
2. 尽量避免类型转换,如果最后要转成float,开始的时候就用float比较好。
3. 不要用double
4. 能用乘法就不要用除法。 比如   3/2 可以换成  3 * 0.5
5. struct的大小尽量是2的倍数,如果不是就调整下,加pad。因为可以在level1 cache里放整数个。
6. 全局变量少用,如果要用,加上static
7. 局部变量也是越少越少。这样register的效率更高
8. 能用switch的地方,就不要用if,因为switch是直接生成跳转表,速度快很多
9. 互相关联的代码之间不要空行,功能不同的代码之间最好空上1行区分开
10. 用const static 代替 #define 定义常量
11. 统一你的代码风格,始终使用同样的命名规则

===================最后==================
生成高效率代码永远是从使用更好更合适的算法开始,但是编译的时候不要忘记打开你的优化开关。希望这个系列给大家带来了一些有用的东西。下个系列见 88


1. http://www.abarnett.demon.co.uk/tutorial.html
2.http://www.microsoft.com/technet/prodtechnol/winxppro/evaluate/xpperf.mspx
3. http://stevezero.com/eecs/cs162_fa03/IOOptimization.pdf
4. David L. Stevens, "TCP/IP Client-Server Programming And Application" Volume 3, Chapter16
5. Andrew S. Tanenbaum "Computer Networks" Chapter 4
6. http://www.agner.org/optimize/optimizing_cpp.pdf

我来说两句】 【发送给朋友】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 C语言基本功教程系列(5) - 文件, Socket 和 其它

 ■ [欢迎对本文发表评论]
用  户:  匿名发出:
您要为您所发的言论的后果负责,故请各位遵纪守法并注意语言文明。

最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放 / 友情链接  
Copyright ©2001-2006 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.0028