16 六月, 2007
显示远程图形窗口 (Displaying remote X clients with Cygwin/X)
运行于Unix/Linux上的软件,越来越多地采用图形界面,特别是软件安装和应用管理。这得益于java,虽然java的图形界面非常丑陋,但确实极大地降低了开发的门槛。
那么,远程如何启用xwindow呢?下面介绍的就是一个基于cygwin上xwindow+openssh的方案。
Displaying remote X clients with Cygwin/XSecure ssh
Run the following in an X terminal:
Username@CygwinHost ~ $ ssh -Y -l username remote_hostname_or_ip_address
Your ssh session should now show you a shell prompt for your remote machine.
Unsecure Telnet
6 五月, 2007
VC: UrlDownloadToFile中的IBindStatusCallback和Custom HTTP headers
UrlDownloadToFile和UrlDownloadToCacheFile是URL Monikers Functions中的简单易用的2个函数。这两个函数在发送下载文件的请求的时候,会自动根据cache control来判别是否需要重新下载,如果需要,则会在HTTP头中自动添加If-Modified-Since和If-None-Match信息,以及对应于该Url的合法的cookie信息。
使用这两个函数下载文件,但是需要添加某项头信息,譬如Referer,或者修改某项头信息,譬如User-Agent,该如何实现呢?这就需要用到这两个函数的最后一个参数“LPBINDSTATUSCALLBACK lpfnCB”。以UrlDownloadToFile为例,它在Binding lpfnCB指向的回调接口的时候,会尝试QueryInterface(IID_IHttpNegotiate),如果这个接口存在,它会调用IHttpNegotiate::BeginningTransaction方法以获取additional Request Headers。所以你可以在IHttpNegotiate::BeginningTransaction方法内实现Custom headers的目的。
具体步骤:
- 声明一个类,实现IBindStatusCallback和IHttpNegotiate接口
- 实现IHttpNegotiate::BeginningTransaction方法,在这个方法内设置或者修改相关HTTP Headers
- 创建这个类的实例,并赋予UrlDownloadToFile函数调用。
参考:SAMPLE: PostMon.exe Demonstrates How to Use URL Moniker to POST Data
例程(Custom request header as "User-Agent: CB/1.0;Referer: http://www.utblog.com"):
查看全文2 五月, 2007
BHO: getflash.dll 引起IE其他控件工作不正常
getflash.dll是FlashGet安装的IE插件,你可以在FlashGet的安装目录下找到这个dll文件。如果启用这个名为“gFlash Class”的BHO插件,可能会造成其他IE控件非正常释放,从而致使IE内存访问异常甚至Crash。参考“防不胜防 Flashget不比速度比流氓”,“Internet Explorer crashes”。有意思的是,FlashGet的开发人员对如何解决此问题的回答是“run...>regsvr32 /u getflash.dll”,解除注册,一了白了。
如果你使用IE6,也可以在“加载项管理”内禁用getflash。
解除注册和在IE内禁用getflash都需要用户手工操作,如果不想这么做,那么可以在页面级(HTML),通过javascript将你的控件插入某一层内(div.innerHTML = "<object..."),并在HTML Body的onUnload事件内删除此层。这种方法可以避免因getflash不正确拦截内部消息造成的控件释放异常。
27 四月, 2007
WB, MFC: 如何改变Web Browser Control的UI
改动IE的Web Browser控件UI,包括自定义或者禁止右键菜单,禁止控件border的3D特性,如何处理鼠标双击事件等等。
通过实现IDocHostUIHandler接口实现。
- 禁止或者自定义菜单:IDocHostUIHandler::ShowContextMenu
- 去除控件border的3D属性:IDocHostUIHandler::GetHostInfo,设置flag为DOCHOSTUIFLAG_NO3DBORDER
- 去除控件窗口的滚动条:IDocHostUIHandler::GetHostInfo,设置flag为DOCHOSTUIFLAG_SCROLL_NO
在IDocHostUIHandler设置前的文档窗口属性(可以被GetHostInfo改变的那部分)不会变化。所以,如果是在DWebBrowserEvents2::DocumentComplete事件内通过ICustomDoc接口设置IDocHostUIHandler的,那么当前窗口的Border和Scroll等属性的设置需要等待下一次Navigation完毕才能生效。有效期一直维持到控件释放或者下一次显式设置。
trick: 在控件显示前,Navigate "about:blank"页面,同时设置IDocHostUIHandler
至于通过重载PreTranslateMessage的方法实现禁止右键菜单的方法(参考:IE的WebBrowser control是一个窗口类,disable right mouse click -context menu-, accelerator keys),限制太多,特别是当此控件被Hosting两次后,连PreTranslateMessage方法也会被屏蔽。
一个简单的例子:Disabling TCppWebBrowser's context menu or "right-click" menu. - by Borland Developer Support Staff
26 四月, 2007
Firefox吃内存,IE的webbrowser控件bug
- Firefox太吃内存,特别是打开包含较多大图片文件的网页时,譬如松松最近发布的:苏州博物馆新馆,上海展览中心
- 微软的webbrowser control是IE的核心,如果你采用CWnd::ShowWindow(SW_HIDE)方式隐藏此控件,会导致整个控件被释放。参考:BUG: WebBrowser Control Destroyed When Hidden, 我的IE是6.0 sp2,已经打了最新的patch,依然有这个问题,可见bug尚未被fix。
23 四月, 2007
DIP: 反转片效果
做自动的反转片效果比较难,因为使用固定的参数只能适合少数照片。我使用的方法是:
- 自动色阶调整,提高原图质量
- Unsharp mask做轻度锐化(.5,.5,2)
- 适当调整亮度(-3)和对比度(+10)
- 大幅提高色彩饱和度(+30)
效果示意,原图:

应用反转效果后:

23 四月, 2007
DIP: 负片冲印(反转负冲)效果
参考pchome上的负片冲印效果PS方法,依次在VC++6.0内实现。
步骤:
- 红色通道“颜色加深”,绿色通道“反相,正片叠底,不透明度30%”,蓝色通道“反相,正片叠底,不透明度50%”
- 分别对三个通道进行色阶调整
- 合并通道,调整亮度和对比度
- 调整色彩明亮度和饱和度
效果示例,原图:

应用反转负冲效果后:

参考:
20 四月, 2007
VC6: 半透明窗口
win2000以后,有新方法SetLayeredWindowAttributes,可以实现此目的。使用SetLayeredWindowAttributes,会影响到整个窗口,包括标题栏以及窗口内的所有控件。这是真正意义上的“半透明窗口”。
如果只是想实现“半透明窗口背景”效果的对话框,可以在首次绘制窗口之前保存被窗口覆盖的那部分的屏幕位图(从显示设备环境CDC对象COPY),然后采用AlphaBlend方法生成半透明效果,再绘制到窗口上。
AlphaBlend API需要msimg32.dll,这个动态库不支持win95/NT。如果想要支持95/NT,可以自己写一个AlphaBlend,毕竟,半透明位图的AC_SRC_OVER 算法相当简单。
20 四月, 2007
ActiveX: 如何获取IE浏览器的客户区屏幕坐标
- 首先要获取顶层浏览器窗口的接口,参考:"Retrieve the Top-Level IWebBrowser2 Interface from an ActiveX Control"
- 注意,IWebBrowser2的ClientToWindow方法,传入参数并非某点坐标,而是客户区的Size。返回的结果是在给定客户区Size的前提下,整个Browser的大小,包含标题栏,工具条,菜单,状态栏等,也包含整个客户区四周的Margin。所以无法通过这个方法取得客户端的left-top坐标
- 取得IHTMLDocument2接口:IWebBrowser2::get_document
- IHTMLWindow2接口:IHTMLDocument2::get_parentWindow
- 取得IHTMLWindow3接口:IHTMLWindow2::QueryInterface(IID_IHTMLWindow3)。注:window对象的所有方法,是通过IHTMLWindow2、IHTMLWindow3、IHTMLWindow4、IHTMLWindow5这4个接口共同实现的。
- 通过IHTMLWindow3接口,取得window.screenLeft和window.screenTop的值。这两个值就是浏览器客户区left-top点相对于屏幕的坐标
- 通过IHTMLDocument2::get_body,获取document.body对象的offsetLeft, offsetTop, offsetWidth, offsetHeight值
- 现在,我们终于可以得到浏览器客户区的屏幕坐标了
31 三月, 2007
IE的WebBrowser control是一个窗口类,disable right mouse click (context menu), accelerator keys
VC++ 6.0
使用WebBrowser控件,它是IE核心控件,文档Load以后,右键点击会出现我们使用IE时一样的context menu。how to disable it?
一个通常的办法,是通过javascript脚本覆盖document.oncontextmenu属性,但是这要求你具有修改网页的权限,而且,IE安全设置必须允许运行javascript。
解决办法:
WebBrowser control是CWnd的继承类,所以,可以重载PreTranslateMessage过程来禁止右键菜单(甚至加上自己的context menu),也可以禁止accelerator keys功能。
29 三月, 2007
为帮助保护您的安全,Internet Explorer 已经限制此文件显示可能访问您计算机的活动内容
XP SP2对使用IE浏览的安全做了大幅提升,“本地计算机区域锁定”就是其一。这是防止恶意网页试图通过提升区域至更少浏览限制的“本地计算机区域”来运行有害代码。
“为帮助保护您的安全,Internet Explorer 已经限制此文件显示可能访问您计算机的活动内容”这样的提示,对于普通用户基本没有影响。但是对于开发者,因为测试本地html文件的需要,此类提示必然频繁出现,极其影响效率。
解决方法:
- Internet选项-->高级-->安全-->允许活动内容在我的计算机上的文件中运行,或者
- 在网页头添加"Web 标记",或者直接修改注册表。参考下面的链接
28 三月, 2007
php: 如何去除URL中的SESSION ID
php.ini有一个参数session.use_trans_sid,用来控制在客户端禁止cookie的时候是否自动重写url从而达到支持session的目的。URL重写的规则是由另外一个参数"url_rewriter.tags"设定的,缺省值为"a=href,area=href,frame=src,input=src,form=fakeentry,fieldset="。
问题来了,当用户打开第一个php页面,后台的php模块接到请求,创建了一个新的session(session_start),但是它在这个时候却无法得知客户端是否支持cookie。如果,系统的session.use_trans_sid是打开(1)的,那么php会重写所有url,将类似"PHPSESSID=93d5b29abebbd31a8cc53e2ac691abcf"字样的session id信息以参数形式记录在url中。
解决办法:
没有完美的解决方案,既然不希望php擅自修改url,那么只有放弃基于url的session实现机制,也就是放弃那些不支持cookie的用户。
设置session.use_trans_sid=0,或者设置url_rewriter.tags=""都可以达到去除url中恼人的PHPSESSID。url_rewriter.tags,可以使用ini_set动态设置,但是session.use_trans_sid不可以动态修改,这似乎和php的版本有关。如果Apache支持,那么修改.htaccess文件,也是可以的
1 三月, 2007
atoi, cookie, strcmp等
- atoi(nptr)函数不做任何错误检验,如果nptr是NULL,将抛出异常,造成segment fault
- strcmp(/strncmp等),如果传入的字符串参数为NULL,会抛出segment fault异常
- 设置cookie,如果不指定expire,则表示此cookie为session cookie。firefox和IE对expire是否存在/是否为空的解释方式是不同的。如果指定expire但是内容为空(expire=;),firefox认定这是一个session cookie,而IE却认为这是一个立即失效的硬盘cookie
- 如果声明了javascript函数onload,firefox会在page load以后自动调用此函数,而IE需要显式调用,即通过设定body的onLoad属性或者js语句调用
5 十一月, 2006
thread safety,就必须保证所有的函数线程安全
用到libxml2的nanohttp模块,虽说libxml2自从2.4.7版本开始就号称已经做到thread safety了,但是,至少这个附加的nanohttp模块在多线程环境中是不安全的。
即便你用--with-threads和--with-thread-alloc选项编译libxml2,也只能保证libxml2库在Parser和内存分配这部分线程安全。nanohttp的不安全不是因为libxml2自己内存管理冲突。
事实上,当多个线程同时调用nanohttp模块的时候,主机地址解析就会发生冲突。用tcpdump查看多线程调用nanohttp fetch的网络包,就发现,经常地,应当向B主机发送的请求却被发送到A主机。
原因是这个模块中调用了非线程安全的函数gethostbyname。处理B主机请求的线程调用gethostbyname(B),它生成的hostent数据覆盖了这之前负责处理A请求的线程的gethostbyname(A)的数据。结果,B主机请求就被发送到了A,张冠李戴了。
要想实现thread safety,就必须使用gethostbyname的线程安全版gethostbyname_r。
同理,象localtime、gmtime之类的函数,与gethostbyuname类似,返回结果的内存分配不是由调用者控制的,都不是thread-safe的。应该用他们各自的reenter版,分别是localtime_r,gmtime_r。
这里找到一份Thread-Safe and Thread-Unsafe Procedure List
20 七月, 2006
UTM, The Universal Transverse Mercator System
近来研究google map,不得已要接触这些Projection System。
好文:http://www.uwgb.edu/dutchs/FieldMethods/UTMSystem.htm
- 赤道上1度(经度)的距离mLE和某纬度lat([-90..90])上1经度的距离mLL之间的关系:
mLL = mLE * cos(radian of lat);
- 100公里双字母表示方法(100-killometers Digraphs):
美国军方(还有整个NATO)使用的表示方法,MGRS中间几位也是用的这种。以上海市(121.4666667E, 31.2333333N)为例,它的UTM数据是:Northing: 3456474, Easting: 353968, Zone: 51R;而不同精度的NATO表示如下:
UQ55(10公里)
UQ5356(1公里)
UQ539564(100米)
UQ53965647(10米)
UQ5396956474(1米)
转换的方法,查看上文中的“100-kilometer Digraphs”,“Determining Grid Coordinates”,“Appendix: The Digraph Lettering System”三个小节。
- google maps的zoom和scale
zoom pixelsPerLonDegree
==== ==================
0 93206.75555555556
1 46603.37777777778
2 23301.68888888889
3 11650.844444444445
4 5825.422222222222
5 2912.711111111111
6 1456.3555555555556
7 728.1777777777778
8 364.0888888888889
9 182.04444444444445
10 91.02222222222223
11 45.51111111111111
12 22.755555555555556
13 11.377777777777778
14 5.688888888888889
15 2.8444444444444446
16 1.4222222222222223
17 0.7111111111111111
放大到最大(zoom=0),在赤道上,Google Map上的一个pixel对应实际距离1.2米左右(111,000/93206.75555555556~=1.2,赤道上,每经度间距离约111公里)
如果你想让自己的地图和Google Map配套使用,那么以上的数据就非常有用。
3 七月, 2006
wxPython: Boa vs. PythonCard
Boa,Python IDE和wxPython GUI开发平台,是一个类似于Delphi的相当优秀的RAD工具。开源,当前版本0.4.4alpha,发布时间是2005/07/11。虽然这个项目的开发进度似乎已经停滞,但是这个版本的Boa还是完全适用小型的GUI应用的开发。作为一个IDE,它具备大多数应该有的功能,也包括code completion, code tips等附加功能。支持自行修改添加Plug-in(如customModuleInfo),支持Custom component等。
不过作为内测alpha版,使用Boa,在开发过程中,一定会碰到很多Bug,想办法绕过去吧。还有,用Sizer实现半可视化的Layout调整,不太方便;以 全路径而不是相对路径调用外部图片等资源,如果不手工修改自动生成代码,则会在实际运行环境中产生异常。
PythonCard, 使用下来,不如Boa方便。不算是统一的集成开发环境(你需要分别调用layout Editor, code Editor);没有采用代码生成方法,而是以特定的资源文件来描述GUI(.rsrc.py),并通过PythonCard.model来解析这个资源 文件。所以严格来说,PythonCard不应该算是一个好的开发平台,更应当被看做是一个封装wxPython的框架(Frame)
参考:PythonCard and Boa Constructor not ready yet
2 七月, 2006
wxPython: wxApp::OnExceptionInMainLoop无效,如何接管异常处理?
wxApp::OnExceptionInMainLoop
“This function is called if an unhandled exception occurs inside the main application event loop. ”
重载了此方法,但是无效,无论什么异常,发生时,这个方法根本不会被执行。没有看过wxPython源码,猜测要么这是一个bug,要么帮助文件中的描述有问题,wxApp::MainLoop()会处理绝大部分Exceptions,所以几乎不存在“unhandled exception”。
如何接管wx App的异常处理?
写一个新的接收三参数( type, value, traceback)的过程,然后覆盖sys.excepthook
例如,在wxApp中将所有的异常都以Message Dialog形式报告给用户:
import sys, trackback
class MyApp(wx.App):
...
#new excepthook method
def _OnExceptionInMainLoop(self, type, value, traceback1):
topwin = self.GetTopWindow()
tblist = traceback.format_list(traceback.extract_tb(traceback1))
dlg = wx.MessageDialog(topwin, '%s : %srn%s'%(type, value, 'rn'.join(tblist)), 'Exception', wx.OK | wx.ICON_ERROR)
try:
dlg.ShowModal()
finally:
dlg.Destroy()
#call default exception handler here
sys.__excepthook__(type, value, traceback1)
application = MyApp(0)
#assigne new exception handler to sys.excepthook attribution
sys.excepthook = application._OnExceptionInMainLoop
application.MainLoop()
因为sys和trackback是通用模块,这个方法也适用于非wxPython应用
参考: http://docs.python.org/lib/module-sys.html
24 六月, 2006
python: locale - setlocale
错误:"locale.Error : unsupported locale setting"
locale.setlocale,最终调用本地OS上的setlocale的c/c++库。
如果本地OS不支持locale,或者本地OS的locale格式不同于locale模块的帮助文档中的描述,调用setlocale都会引发以上异常
以winxp简体中文,python 2.4为例,locale.setlocale(0,'')会返回locale字符串"Chinese_People's Republic of China.936",而不是locale.getdefaultlocale返回的"zh_CN.cp936",更多设置,需参考VC++的setlocale方法。而在中文Linux上,同样的方法,会返回标准的"xx_XX.xxx"格式字符串,譬如"zh_CN.GB18030",参考POSIX的setlocale man页。
严格说,这不算是bug。不过,为了提高Python程序的可移植性,保证这门语言的平台无关特性,最好能在将来的版本中解决这个问题
8 六月, 2006
python: 元组(tuple)的标准定义
元组(tuple),作为python序列数据类型的一种,标准定义如下:
A tuple consists of a number of values separated by commas
某些文章(譬如《A Byte of Python》,《Dive Into Python》)的定义却是:(与列表(list)类似的)在圆括号中用逗号分割的数据类型。
其实,圆括号"()"只在tuple输出的时候使用,而不是元组数据定义所必须的。
temp = 1,2,3,4 等同于temp = (1,2,3,4)
这就可以理解对于一个字典数据dictA,我们为什么能够使用for key, val in dictA.items()这样的语句,因为它和for (key, val) in dictA.items()是一样的
只有在声明空元组的时候,圆括号才是必须的
emptyTuple=()
其它:
一个元素的元组:
temp = 1, 等同于 temp = (1,)
8 六月, 2006
pyton: The __del__ method is not a reliable cleanup mechanism
Python初学者的经典教程《A Byte of Python》,在讲述“Class and Object Variables”的时候,有一个Person Class的例子,其中包括__init__和__del__实现。
比较C++,__init__类似于constructor,而__del__类似于destructor。实际上,Python的实现机制和C++有很大区别,特别是对于__del__。
作者也在此文末尾,特地提醒到:“
The __del__ method is run when the object is no longer
in use and there is no guarantee when that method will
be run. If you want to explicitly do this, you just have to use the
del statement which we have used in previous examples.”
意思是说,如果想保证__del__顺利执行,需要显式调用del函数。否则的话,python会在垃圾收集的时候释放这些对象占用的内存,那时候,很难保证全局域中的Class声明本身是否还可用。很有可能你会在程序退出的时候,发生类似异常“exceptions.AttributeError:"'NoneType' object has no attribute...”。"NoneType"就是因为类声明已经先于对象被释放了(be set to None)
所以说,“The __del__ method is not a reliable cleanup mechanism”。你可以通过添加另外的方法实现这部分功能,如果一定要使用__del__的话,请务必显式(explicit)调用del来释放对象。
1 六月, 2006
IP首部拆解——中国协议分析网
see http://www.cnpaf.net/class/TCPANDIP/0532918532739185.html
摘要:
- bit0~3: 目前的协议版本号是4,因此IP有时也称作IPv4
- bit4~7: 首部长度指的是首部占32bit字的数目,包括任何选项。由于它是一个4比特字段,因此首部最长为60个字节。普通IP数据报(没有任何选择项)字段的值是5
- TOS: 包括一个3bit的优先权子字段(现在已被忽略),4bit的TOS子字段和1bit未用位但必须置0。4bit的TOS分别代表:最小时延、最大吞吐量、最高可靠性和最小费用。4bit中只能置其中1bit。如果所有4bit均为0,那么就意味着是一般服务
- 总长度字段: 整个IP数据报的长度,以字节为单位。利用首部长度字段和总长度字段,就可以知道IP数据报中数据内容的起始位置和长度。由于该字段长16比特,所以IP数据报最长可达65536字节。当数据报被分片时,该字段的值也随着变化
- 标识字段: 唯一地标识主机发送的每一份数据报。通常每发送一份报文它的值就会加1
- 3位分片标识: R:保留未用;DF:Don't Fragment,“不分片”位,如果将这一比特置1 ,IP层将不对数据报进行分片;MF:More Fragment,“更多的片”,除了最后一片外,其他每个组成数据报的片都要把比特置1
- Fragment Offset:该片偏移原始数据包开始处的位置,偏移的字节数是该值乘以8
- TTL: Time-To-Live,生存时间字段设置了数据报可以经过的最多路由器数。它指定了数据报的生存时间。TTL的初始值由源主机设置(通常为32或64),一旦经过一个处理它的路由器,它的值就减去1。当该字段的值为0时,数据报就被丢弃,并发送ICMP报文通知源主机
- 首部检验和字段: 根据IP首部计算的检验和码。它不对首部后面的数据进行计算。ICMP、IGMP、UDP和TCP在它们各自的首部中均含有同时覆盖首部和数据检验和码。为了计算一份数据报的IP检验和,首先把检验和字段置为0。然后,对首部中每个16 bit 进行二进制反码求和(整个首部看成是由一串16 bit的字组成),结果存在检验和字段中。当收到一份IP数据报后,同样对首部中每个16 bit 进行二进制反码的求和。由于接收方在计算过程中包含了发送方存在首部中的检验和,因此,如果首部在传输过程中没有发生任何差错,那么接收方计算的结果应该 为全1。如果结果不是全1(即检验和错误),那么IP就丢弃收到的数据报。但是不生成差错报文,由上层去发现丢失的数据报并进行重传
typedef struct _iphdr //定义IP首部
{
unsigned char h_verlen; //4位首部长度,4位IP版本号
unsigned char tos; //8位服务类型TOS
unsigned short total_len; //16位总长度(字节)
unsigned short ident; //16位标识
unsigned short frag_and_flags; //3位标志位+13位片偏移
unsigned char ttl; //8位生存时间 TTL
unsigned char proto; //8位协议 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校验和
unsigned int sourceIP; //32位源IP地址
unsigned int destIP; //32位目的IP地址
}IP_HEADER;
26 五月, 2006
sprintf的字符缓存越界
int sprintf(char *str, const char *format, ...);
要保证目标字符串缓存str的大小足够大。否则,会引起不可知错误。什么叫“不可知”,就是不可预测,就是让你很头晕,让你很后悔为啥要做一个程序员。
正在写的一个后台的服务进程,在收到SIGTERM(SIGKILL)信号的时候,结束所有的线程,释放所有的资源,并正常终止。然而昨天下午,这个服务突然不能被kill掉了。花了几个小时的debug,才发现原来错误就起源于一小段测试例程中的这个小小的不起眼的sprintf函数。缓冲区稍微小了那么几个字符,溢出覆盖了线程的数据区。而那些傻不拉唧的threads哪里知道它们的一亩三分地已经被人践踏,依旧照着这些莫名其妙的数据执行着莫名其妙的指令。结果是,我莫名其妙地浪费了很多时间。
建议:
- 尽量不要采用sprintf之类的需要主观确认缓冲区安全的函数,采用snprintf,或者asprintf之类的函数替代
- gcc/g++编译器最好能给出可能越界的Hint
26 四月, 2006
Socket编程中发送接收缓冲大小设置
对于TCP,因为是可靠连接,所以,一个包被抛弃(发送方或者接受方),底层协议会要求再发送一次,或者阻塞在应用层。
而如果使用UDP,那么必须由应用层自己作逻辑判断,保证数据的完整性。否则阻塞时,包会被简单地丢弃。
Linxu 2.4中,
- 发送缓存的初始大小 : sysctl.net.core.wmem_default = 65536
- 发送缓存的最大值(bytes):sysctl.net.core.wmem_max = 65535
- 接收缓存的初始大小 : sysctl.net.core.rmem_default = 65536
- 接收缓存的最大值(bytes):sysctl.net.core.rmem_max = 65535
应用层,使用setsockopt(sock, SOL_SOCKET, SO_RCVBUF/SO_SNDBUF, &bufsize, (socklen_t)len)来设置send/receive buffer的最大值,此值不能超过sysctl中设置的最大对应值。所以,如果想增加缓冲大小,必须先修改系统配置,可以使用sysctl命令(reboot不保留),或者修改/etc/sysctl.conf(sysctl -p或者reboot后有效)
缓冲区增大,无疑会加重系统开销,要根据实际需求进行调节,不是大了就好。
对于UDP,写缓冲区和TCP不一样,UDP其实没有所谓的写缓冲区,SO_SNDBUF只是设置了当前发送包的最大尺寸
21 四月, 2006
GNU C/C++中,sizeof (struct xys) 与struct成员size之和不一致
struct xyzstruct{
char a;
double b;
} xyz;
32位的编译器下,因为性能的考虑,对于struct(也包含union等其它数据结构)的大小和每个成员变量的位置都根据寄存器/内存访问值的边界要求做了align。这就使得sizeof(xyz) = 16 而不是实际成员所占空间之和 sizeof(char) + sizeof(double) = 9
一般来说,这不成问题,不过,对于那些空间紧张,或者有特殊要求的应用,就需要考虑struct的紧凑实现了。
譬如,将服务器端传入的固定格式的数据包直接映射到一个结构上去,便于访问:
union {
char bytes[9];
struct xyzstruct data;
} uvw;
如果这里的struct/union是紧凑实现的,那么我们可以通过uvw.data来直接访问bytes中的数据,不用再另外编写代码了。
解决办法:
1. gcc的编译选项“-fpack-struct”
可以去除struct结构中额外的hole,缺点是,影响应用中所有的struct,包括从其它库中引入的struct结构
2. __attribute__ ((packed)) 声明
struct {char a; double b;} xyz __attribute__ ((packed));
不过这种简单格式的声明只对C有效,在C++中,你必须对struct中的每个成员(size>1)进行这样的声明:
struct {
char a;
double b __attribute__ ((packed));
int c __attribute__ ((packed));
} xyz;
3. 预编译选项 #pragma pack(n)
这里的n是通知编译器对此“pragma”行后出现的所有数据结构(包括stuct/union)采用n字节方式对齐(align)。如果n=1,那么表示全紧凑,struct中不会出现任何占位的hole。如果n是空,表示回复到编译器缺省的设置(一般=8)
#pragma pack(1)
//此段内所有数据结构全紧凑
#pragma pack()




