DownLoad:
https://addons.mozilla.org/en-US/firefox/downloads/file/12448/live_http_headers-0.13.1-fx.xpi
Usage:
为无为 事无事 味无味
由于国内已经无法访问blogspot, 东华小屋搬家至: http://www.truevue.org/
1.MSComm控件两种处理通讯的方式
MSComm控件提供下列两种处理通讯的方式:事件驱动方式和查询方式。
1.1 事件驱动方式
事件驱动通讯是处理串行端口交互作用的一种非常有效的方法。在许多情况下,在事件发生时需要得到通知,例如,在串口接收缓冲区中有字符,或者 Carrier Detect (CD) 或 Request To Send (RTS) 线上一个字符到达或一个变化发生时。在这些情况下,可以利用 MSComm 控件的 OnComm 事件捕获并处理这些通讯事件。OnComm 事件还可以检查和处理通讯错误。所有通讯事件和通讯错误的列表,参阅 CommEvent 属性。在编程过程中,就可以在OnComm事件处理函数中加入自己的处理代码。这种方法的优点是程序响应及时,可靠性高。每个MSComm 控件对应着一个串行端口。如果应用程序需要访问多个串行端口,必须使用多个 MSComm 控件。
1.2 查询方式
查询方式实质上还是事件驱动,但在有些情况下,这种方式显得更为便捷。在程序的每个关键功能之后,可以通过检查 CommEvent 属性的值来查询事件和错误。如果应用程序较小,并且是自保持的,这种方法可能是更可取的。例如,如果写一个简单的电话拨号程序,则没有必要对每接收一个字 符都产生事件,因为唯一等待接收的字符是调制解调器的 "确定"响应。
2.MSComm 控件的常用属性
MSComm 控件有很多重要的属性,但首先必须熟悉几个属性。
CommPort | 设置并返回通讯端口号。 |
Settings | 以字符串的形式设置并返回波特率、奇偶校验、数据位、停止位。 |
PortOpen | 设置并返回通讯端口的状态。也可以打开和关闭端口。 |
Input | 从接收缓冲区返回和删除字符。 |
Output | 向传输缓冲区写一个字符串。 |
下面分别描述:
CommPort属性:设置并返回通讯端口号。
语法 object.CommPort[value ] (value 一整型值,说明端口号。)
说明 在设计时,value 可以设置成从 1 到 16 的任何数(缺省值为 1)。但是如果用 PortOpen 属性打开一个并不存在的端口时,MSComm 控件会产生错误 68(设备无效)。
注意:必须在打开端口之前设置 CommPort 属性。
RThreshold 属性:在 MSComm 控件设置 CommEvent 属性为 comEvReceive 并产生 OnComm 之前,设置并返回的要接收的字符数。
语法:object.Rthreshold [ = value ](value 整型表达式,说明在产生 OnComm 事件之前要接收的字符数。 )
说明:当接收字符后,若 Rthreshold 属性设置为 0(缺省值)则不产生 OnComm 事件。例如,设置 Rthreshold 为 1,接收缓冲区收到每一个字符都会使 MSComm 控件产生 OnComm 事件。
CTSHolding 属性:确定是否可通过查询 Clear To Send (CTS) 线的状态发送数据。Clear To Send 是调制解调器发送到相联计算机的信号,指示传输可以进行。该属性在设计时无效,在运行时为只读。
语法: object.CTSHolding(Boolean)
Mscomm 控件的 CTSHolding 属性设置值:
True Clear To Send 线为高电平。
False Clear To Send 线为低电平。
说明:如果 Clear To Send 线为低电平 (CTSHolding = False) 并且超时时,MSComm 控件设置 CommEvent 属性为 comEventCTSTO (Clear To Send Timeout) 并产生 OnComm 事件。
Clear To Send 线用于 RTS/CTS (Request To Send/Clear To Send) 硬件握手。如果需要确定 Clear To Send 线的状态,CTSHolding 属性给出一种手工查询的方法。
详细信息 有关握手协议,请参阅 Handshaking 属性。
SThreshold 属性: MSComm 控件设置 CommEvent 属性为 comEvSend 并产生 OnComm 事件之前,设置并返回传输缓冲区中允许的最小字符数。
语法 object.SThreshold [ = value ]
value 整形表达式,代表在 OnComm 事件产生之前在传输缓冲区中的最小字符数。
说明:若设置 Sthreshold 属性为 0 (缺省值),数据传输事件不会产生 OnComm 事件。若设置 Sthreshold 属性为 1,当传输缓冲区完全空时,MSComm 控件产生 OnComm 事件。如果在传输缓冲区中的字符数小于 value ,CommEvent 属性设置为 comEvSend,并产生 OnComm 事件。comEvSend 事件仅当字符数与 Sthreshold 交叉时被激活一次。例如,如果 Sthreshold 等于 5,仅当在输出队列中字符数从 5 降到 4 时,comEvSend 才发生。如果在输出队列中从没有比 Sthreshold 多的字符,comEvSend 事件将绝不会发生。
Handshake 常数
常数 | 值 | 描述 |
comNone | 0 | 无握手。 |
comXonXoff | 1 | XOn/Xoff 握手。 |
comRTS | 2 | Request-to-send/clear-to-send 握手。 |
comRTSXOnXOff | 3 | Request-to-send 和 clear-to-send 握手皆可。 |
OnComm 常数
常数 | 值 | 描述 |
comEvSend | 1 | 发送事件。 |
comEvReceive | 2 | 接收事件。 |
comEvCTS | 3 | clear-to-send 线变化。 |
comEvDSR | 4 | data-set ready 线变化。 |
comEvCD | 5 | carrier detect 线变化。 |
comEvRing | 6 | 振铃检测。 |
comEvEOF | 7 | 文件结束。 |
Error 常数
常数 | 值 | 描述 |
comEventBreak | 1001 | 接收到中断信号 |
comEventCTSTO | 1002 | Clear-to-send 超时 |
comEventDSRTO | 1003 | Data-set ready 超时 |
comEventFrame | 1004 | 帧错误 |
comEventOverrun | 1006 | 端口超速 |
comEventCDTO | 1007 | Carrier detect 超时 |
comEventRxOver | 1008 | 接收缓冲区溢出 |
comEventRxParity | 1009 | Parity 错误 |
comEventTxFull | 1010 | 传输缓冲区满 |
comEventDCB | 1011 | 检索端口 设备控制块 (DCB) 时的意外错误 |
InputMode 常数
常数 | 值 | 描述 |
comInputModeText | 0 (缺省) | 通过 Input 属性以文本方式取回数据。 |
comInputModeBinary | 1 | 通过 Input 属性以二进制方式检取回数据。 |
CDHolding 属性:通过查询 Carrier Detect (CD) 线的状态确定当前是否有传输。Carrier Detect 是从调制解调器发送到相联计算机的一个信号,指示调制解调器正在联机。该属性在设计时无效,在运行时为只读。
语法 object.CDHolding
设置值:CDHolding 属性的设置值为:
设置 | 描述 |
True | Carrier Detect 线为高电平 |
False | Carrier Detect 线为低电平 |
说明:注意当 Carrier Detect 线为高电平 (CDHolding = True) 且超时时,MSComm 控件设置CommEvent 属性为 comEventCDTO(Carrier Detect 超时错误),并产生 OnComm 事件。
注意 在主机应用程序中捕获一个丢失的传输是特别重要的,例如一个公告板,因为呼叫者可以随时挂起(放弃传输)。
Carrier Detect 也被称为 Receive Line Signal Detect (RLSD)。
数据类型:Boolean
DSRHolding 属性:确定 Data Set Ready (DSR) 线的状态。Data Set Ready 信号由调制解调器发送到相连计算机,指示作好操作准备。该属性在设计时无效,在运行时为只读。
语法:object.DSRHolding
object 所在处表示对象表达式,其值是"应用于" 列表中的对象。
DSRHolding 属性返回以下值:
值 | 描述 | 说明 |
True | Data Set Ready 线高 | 当 Data Set Ready 线为高电平 (DSRHolding = True) 且超时时,MSComm 控件设置 CommEvent 属性为 comEventDSRTO(数据准备超时)并产生 OnComm 事件。 |
False | Data Set Ready 线低 |
Settings 属性: 设置并返回波特率、奇偶校验、数据位、停止位参数。
语法: object.Settings[ = value]
说明:当端口打开时,如果 value 非法,则 MSComm 控件产生错误 380 (非法属性值)。
Value 由四个设置值组成,有如下的格式:
"BBBB,P,D,S"
BBBB 为波特率,P 为奇偶校验,D 为数据位数,S 为停止位数。value 的缺省值是:
"9600,N,8,1"
InputLen 属性:设置并返回 Input 属性从接收缓冲区读取的字符数。
语法 object.InputLen [ = value]
InputLen 属性语法包括下列部分:
value 整型表达式,说明 Input 属性从接收缓冲区中读取的字符数。
说明:InputLen 属性的缺省值是 0。设置 InputLen 为 0 时,使用 Input 将使 MSComm 控件读取接收缓冲区中全部的内容。
若接收缓冲区中 InputLen 字符无效,Input 属性返回一个零长度字符串 ("")。在使用 Input 前,用户可以选择检查 InBufferCount 属性来确定缓冲区中是否已有需要数目的字符。该属性在从输出格式为定长数据的机器读取数据时非常有用。
EOFEnable 属性:确定在输入过程中 MSComm 控件是否寻找文件结尾 (EOF) 字符。如果找到 EOF 字符,将停止输入并激活 OnComm 事件,此时 CommEvent 属性设置为 comEvEOF,
语法:object.EOFEnable [ = value ]
EOFEnable 属性语法包括下列部分:
value 布尔表达式,确定当找到 EOF 字符时,OnComm 事件是否被激活,如"设置值"中所描述。
value 的设置值:
True 当 EOF 字符找到时 OnComm 事件被激活。
False (缺省)当 EOF 字符找到时 OnComm 事件不被激活。
说明:当 EOFEnable 属性设置为 False,OnComm 控件将不在输入流中寻找 EOF 字符。
3.错误消息(MS Comm 控件)
下表列出 MSComm 控件可以捕获的错误:
值 | 描述 |
380 | 无效属性值 comInvalidPropertyValue |
383 | 属性为只读 comSetNotSupported |
394 | 属性为只读 comGetNotSupported |
8000 | 端口打开时操作不合法 comPortOpen |
8001 | 超时值必须大于 0 |
8002 | 无效端口号 comPortInvalid |
8003 | 属性只在运行时有效 |
8004 | 属性在运行时为只读 |
8005 | 端口已经打开 comPortAlreadyOpen |
8006 | 设备标识符无效或不支持该标识符 |
8007 | 不支持设备的波特率 |
8008 | 指定的字节大小无效 |
8009 | 缺省参数错误 |
8010 | 硬件不可用(被其它设备锁定) |
8011 | 函数不能分配队列 |
8012 | 设备没有打开 comNoOpen |
8013 | 设备已经打开 |
8014 | 不能使用 comm 通知 |
8015 | 不能设置 comm 状态 comSetCommStateFailed |
8016 | 不能设置 comm 事件屏蔽 |
8018 | 仅当端口打开时操作才有效 comPortNotOpen |
8019 | 设备忙 |
8020 | 读 comm 设备错误 comReadError |
8021 | 为该端口检索设备控制块时的内部错误 comDCBError |
命令 说明 快捷键
:tab new 新建一个标签页
:tabedit 在新标签页打开文件
:tabnext 下一个标签页 <C-PageDown>
:tabp[revious] 上一个标签页 <C-PageUp>
upvar ?level? varName localvar
example:1 tcl>set drv 5
2 tcl>set foo "oai21_e5m_hvt"
3 tcl>regsub {_(_v\d)?e(\d+)} $foo "_ \1 e$drv" goo
4 1
5 tcl>echo $goo
6 oai21_e5m_hvt
7 tcl>echo $foo
8 oai21_e5m_hvt
9 tcl> string match $foo $goo
10 0
11 tcl>string length $foo
12 13
13 tcl>string length $goo
14 14
15 tcl>string index $goo 6
16
17 tcl>string index $foo 6
18 e
19 tcl>
1.0.0 P5EE 1 的首发版版本号后面也可以跟一个连字符和一些文字,来表示特别的版本,或者给出额外的信息。例如 1.1.4-bender 注意,这是一个狂欢版 1.5.0-pre1 注意这不是最后的版本,而是预览版。 在perl5.6.0中,你可以使用象v2.0.0这样的版本,但是在前几版的perl是不允许的。所以要把一个tuple版本号转换成一个用$VERSION表示的版本号字符串,使用正常的整数来表示主修订号,三个数字来做版本号和三个数字来做子版本号。例如:
1.0.1 P5EE 1.0的第二次发布版
1.0.10 P5EE 1.0的第二次发布版的第一次修正版
1.1.0 P5EE 1.1的首发版
2.0.0 P5EE 2 的首发版
1.1.6 -> 1.001006
2.0.0 -> 2.000000
这样,perl就可以通过大于和小于比较两个版本字符串。 LinuxForum中有一篇关于 软件发行惯例 的中文译版:http://www.linuxforum.net/books/srp/Software-Release-Practice-HOWTO.html
# story count
my $sc = 0;
也许要别人理解代码需要包含一些整齐的注释。有时一个简单的单行注释就可以解释后面代码的用途。另外,我们有时还需要对一个复 杂的算法需要每行都要注释。Kernighan 和 Pike 写的《Practice of Programming》中关于注释的部分值得一看。
return($user, $form, $constants);
当数组不确定的时候也许是一个例外。
my @return = ($user, $form);
push @return, $constants if $flag;
return @return;
尽管如此,但是,为了提高代码的效率和可读性,我们更趋向于编写这样的代码:
if ($flag) {
return($user, $form, $constants);
} else {
return($user, $form);
}
my $huge_data_structure = get_huge_data_structure();
do_something_with($huge_data_structure);
undef $huge_data_structure;
my $path = "$dir/$file"; # 错
my $path = catfile($dir, $file); # 对
my $dir = "."; # 错
my $dir = curdir(); # 对
mkdir("/path"), mkdir("/path/to"), ... # 错
`mkdir /path`; `mkdir /path/to`, ... # 大错特错
mkpath("/path/to/my/dir", 0, 0775); # 对
请使用 opendir()
和 readdir()
来代替 glob 操作符(glob('*') 或者 <*>)
。注意 glob()
在perl5.6中比以往版本更轻便了,但它还是不十分可靠,每个perl的安装都可以选择通过 File::Glob
模块来用本地的习惯来代替这个默认的。 不要为了任何事而使用向*foo这样的符号表 globs(和上面提到的 glob 不一样),除非有必要必须直接操作符号表。其实这从来都是不必要的。
$Minimum = 10; # 错
$MAXIMUM = 50; # 对
其他变量小写,用下划线来连接单词。这些单词通常都用名词(一般都是单数名词),除非变量被用来指示某些动作的标记,那么这些变量的名字可以使用描述该动作的动词(或者是动名词)。
$thisVar = 'foo'; # 错
$this_var = 'foo'; # 对
$work_hard = 1; # 对,动词,布尔类型的标记
$running_fast = 0; # 对,动名词,布尔类型的标记
数组和哈希应该是复数的名词,不管是正常的数组和哈希还是数组引用和哈希引用。不要给引用命名为ref或者将其类型加入到名字当中。
@stories = (1, 2, 3); # 对
$comment_ref = [4, 5, 6]; # 错
$comments = [4, 5, 6]; # 对
$comment = $comments->[0]; # 对
让名字易理解。不要使用象$sc这样的名字,你应该用"$story_count"。 方法和函数(除了那些特殊情况,比如AUTOLOAD)应该由动词开头,然后后面跟着完成动作的词汇。词组组成的名字应该全部小写,并用下划线来连接单 词,为了跟'perl样式'指导还有那些CPAN上大部分模块保持一致。这些方法应该尽可能地描绘出它要执行什么,和它要返回什么数据。
$obj->getStory(); # 错
$obj->setStoryByName(); # 又错了
$obj->getStoryByID(); # 还是错!这不是Java!
$obj->get_story(); # 对
$obj->set_story_by_name(); # 对
$obj->get_story_by_id(); # 对
以下划线开头的方法和函数是特殊的:它们在当前文件之外是无法使用的。(也就是'private'--私有的)。但这不是代码本身强制要求的,而只是编程人员的习惯而已。 对于大的for循环结构,不要使用$_,而是用具名的变量。不要用$_(或者假想它)除非你非常明确是怎么回事,或者需要它的时候(比如在map()和grep()中)。
for (@list) {
print; # 对;每个人都知道这是什么意思
print uc; # 不好;很少有人知道这个
print uc $_; # 看起来好一些了
}
注意,如果可能的话,请使用特殊变量'_'。它是一个占位符,可以传递给stat()和文件测试符,它让重新判断文件的状态变 得简单一些。在下面这个例子中。在每个文件测试中都要使用变量$file。使用'_'来代替是个不错的选择。尽管最后一次测试的文件和你想像的一样,你还 是应该小心一些。
if (-d $file) { # $file现在是一个目录
# ...
} elsif (-l _) { # $file现在是一个symlink # ...
}
包的名字应该每个单词的第一个字母大写,其余的小写。 P5EE::Standard # 好在POD文档中全部使用小写。
P5EE::Authz # 好
P5EE::MainCode # 好
P5EE::styleguide # 对于文档来说还不错为模块命名应该遵循下面几条规则。 所有被p5ee@perl.org邮件列表广泛支持的P5EE的服务都应该进入P5EE的包中 '命名样式'应该和CPAN上的模块类似。 '选择命名'借鉴CPAN上其他模块的先例。 '选择命名'借鉴J2EE的先例。 那些还没有确定要作为对象被初始化的包应该用一个'形容词'或者'概念'来作名字(也就是 P5EE::Standard) 那些已经确定要作为对象被促使化的模块和类包应该用伴有隐含变化形容词含义的名词来作名字(也就是说 P5EE::Authen::Principal)。
* x?emacs: cperl-mode
.xemacs/custom.el:
------------------
(custom-set-variables
'(cperl-indent-level 4)
'(cperl-continued-statement-offset 4)
'(cperl-tab-always-indent t)
'(indent-tabs-mode nil)
)
* vim
.vimrc:
-------
set expandtab " replaces any tab keypress with the appropriate number of spaces
set tabstop=4 " sets tabs to 4 spaces
" 将制表符换成适当数量的空格
" 将制表符换成4个空格
foo(@bar) ; # 错
foo(@bar); # 对
垂直对齐。
my $foo = 1;
my $bar = 2;
my $xyzzy = 3;
open(FILE, $fh) or die $!;
open(FILE2, $fh2) or die $!;
$rot13 =~ tr[abcedfghijklmnopqrstuvwxyz]
[nopqrstuvwxyzabcdefghijklm];
# note we use a-mn-z instead of a-z,
# for readability
$rot13 =~ tr[a-mn-z]
[n-za-m];
为了增加可读性,下列操作时需要一些空白: * 在做不同工作的代码块间,添加空行。 * 在变量声明完成之后,添加空行。 * 在最终的return()代码之前,添加空行。 * 在块的前面和后面添加空行,如果前面是注释的话,则不用添加空行。 一个例子:
# this is my function! 这是我的函数
sub foo {
my (@data) = @_;
my $obj = new Constructor;
my ($var1, $var2);
$obj->setFoo($data[1]);
$var1 = $obj->getFoo(1);
$var2 = $obj->getFoo($var1);
display($var1, $var2);
return($data[0]);
}
print 1;
for(@list) # 错
for (@list) # 对
my ($ref) # 对
my($ref) # 首选
localtime ($time); # 错
localtime($time); # 对
对带圆括号的列表和标量上下文要仔细!
my @array = ('a', 'b', 'c');
my ($first_element) = @array; # a
my ($first_element) = ('a', 'b', 'c'); # a
my $element_count = @array; # 3
my $last_element = ('a', 'b', 'c'); # c
永远在函数后面加上圆括号,尽管没有参数也是如此。但有一些例外,比如列表操作符(比如print)和一元操作符(像undef,delete,uc等等)。 如果为了可读性,可以在圆括号中添加空格,否则不要添加。
for ( map { [ $_, 1 ] } @list ) # 可以
for ( @list ) # 也还可以。
在多行的表达式中,用开始的语句或前圆括号来对齐后圆括号都可以。
@list = qw(
bar
baz
); # 正确
if ($foo && $bar && $baz
&& $buz && $xyzzy
) {
print $foo;
}
在后圆括号之后是否添加空格取决于它后面要跟什么。
print foo(@bar), baz(@buz) if $xyzzy;
还要注意,在允许省略圆括号的情况下-单行控制流程表达式,比如if $xyzzy,对于程序员来说,如果你十分明确它的含义的话,你可以省略圆括号。其实在上面的这种情况在$xyzzy两边是完全可以省略掉圆括号的。所以 就省略掉它们,以增加可读性。如果有问题的话,那最好就别省略圆括号了。 同样原则也适用于perl的内置函数,当你很确定的情况下(例如,在语句中只有一句调用函数的语句,或者函数调用被流控制操作符分割)。用户自定义函数必 须加上圆括弧。
print 1, 2, 3; # 好的
delete $hash{key} if isAnon($uid); # 好的
不管怎样,如果有什么疑惑的情况,最好加上圆括弧,记住perl样式man文档中Larry Wall的一句话: 当你有疑惑的时候,加上圆括号,至少,它可以让一些可怜的笨家伙在vi中能用%跳舞。(在vi中%用来寻找匹配的括号) 尽管你不处于疑惑之中,将来使用你的代码的人,就算是为他们的大脑神经做做公益事业,你还是加上圆括号吧,省得将来他们自己加括号也许会加错地方。 所以,当程序员非常清楚的情况下,省略圆括号,但是如果有任何问题的话,就不要省略它们。
while (<$fh>){ # 错
while (<$fh>) { # 对
一行的代码块可以写在一行中。那代码后面的分号可以省略。 for (@list) { print }否则,在每一行代码结束的地方添加分号,在第一行写关键字和前花括号,后花括号和后面的关键字写在一行。
for (@list) {perl样式中常用"单臂elses":(译者注:就是else旁边只有一个单花括号。)
print;
smell();
}
# 对
if ($foo) {
print;
}
else {
die;
}
# 错
if ($foo) {
print;
} else {
die;
}
print $x , $y; # 错注意"&&"和"||"的优先级高于"and"和"or"。除此之外完全相同。建议使用低优先级的来控制流程,高优先级的用来测试/返回值。例如:
print $x, $y; # 对
$x = 2 >> 1; # 好
$y = 2**2; # 好
$bool = $flag1 or $flag2; # 错误!无法运行注意上面"and"很少使用and,因为上面的语句比用"if"写要好一些。
$value = $foo || $bar; # 正确
open(FILE, $file) or die $!;
$true = foo($bar) && baz($buz);
foo($bar) and baz($buz);
baz($buz) if foo($bar);大多数情况下,and和&&,or和||之间的混淆可以通过使用圆括号很好地解决。如果你不使用圆括号,那么你必须正确使用 操作符。但如果你使用了圆括号--通常,如果有问题的话,应该使用--那么不管你用什么操作符都关系不大。从易读角度来看也好,从美学角度来看也好,一定 要在你的代码块中保持风格一致。 在很长的代码行中在操作符之后断行,但"and","or","&&","||"例外。对于二元的操作符来讲,符号两边的数据要尽量保持 整齐。
print "foo" . "bar" . "baz"
. "buz"; # 错
print "foo" . "bar" . "baz" .
"buz"; # 对
print $foo unless $x == 3 && $y ==
4 && $z == 5; # 错
print $foo unless $x == 3 && $y == 4
&& $z == 5; # 对
$foo{$bar{baz}{buz}}; # 不错总的来说,单引号之间表示是纯字符,双引号之间表示是允许内插的文本。 在花括号之间的名称和当使用=>符号的情况下可以省略引号,但是一定要小心这个名称不要和函数名重复。如果有重复,则必须使用引号。
$foo{ $bar{baz}{buz} }; # 更好
$what{'time'}{it}{is} = time();当创造复合语句的时候,把主要的执行动作放在前面。
open(FILE, $fh) or die $!; # 对使用"打印至"来代替重复使用print语句。
die $! unless open(FILE, $fh); # 错
print "Starting\n" if $verbose; # 对
$verbose && print "Starting\n"; # 错
print <只要记住,除非你在"打印至"的记号两边写上单引号(<<'EOT'),那么其间的文本是可以内插的。所以要打印"$"和"@"符号是需要转义的。