请神赐予我详和吧,让我接受那些我不能改变的事实;请神赐予我勇气吧,让我改变那些我能够改变的事情;并且可以明辨这两者的区别。

发布新日志

  • SVN权限控制文件中用户名参数为空时用户依然可读

    2008-03-28 15:40:40



    SVN权限控制文件中用户名参数为空时用户依然可读:
    权限控制文件如下:
    [repo:/]
    candy=rw
    cli=r

    [repo:/trunk]
    candy=rw
    cli=
    使用cli帐户从网页访问repo:/trunk目录后,依然可读此目录的内容。可是用户名参数为空时,不是应该提示Forbbiden吗?
  • 发现了MSN的一个BUG

    2007-11-30 22:14:58

        平时也不怎么用MSN,今天用其聊天的时候发现一个BUG,也许常用MSN的人已经发现了,这个问题,在我在某个网络公司就职的时候,也在所测的软件中发现了和这个一样的BUG,看来这个问题是比较容易出现和被忽略的。这个问题就是,当你的IE是开着一个或多个,并打开了某网页的时候,在MSN的对话中,点开对方发送过来的链接,将不会重新打开一个IE去找开这个链接的页面,而是将最上层的IE更新了,你将失去你原来打开的网页。

       这个问题还是比较讨厌的,如果被更改掉的是比较有用的网页,还需要重新打开。可是这个BUG是属于什么类呢。应该不是功能上的BUG,当然更不是性能上的。界面的?也不是。应该是易用性,对是易用性这块的,关于易用性,可以发掘的东西很多,可能被忽略的东西也很多,测试用例最不容易覆盖可能存在的一些问题,是需要靠经验积累的。

        有一些在代码中处理的问题,我们可能会想当然的认为他是这样或那样处理的,而可能真实的处理方式是我们所想不到的,所以有一些地方的问题也是很容易被忽略的。就像我在某个软件中的测试中,某两个不相关的WEB页面,我在第一个页面所进行的刷新等动作会影响到另一个页面的显示结果。这个也是测试用例不容易覆盖的,但是如果我们能对详细设计文档进行测试,或者直接的白盒测试,也许能更加主动的发现这些问题,黑盒测试是有一定的被动性的。

       如何能在黑盒测试中获得更大的主动性,除了积累经验之外,多和开发人员探讨一下系统的实现方式,过程是很必要的。所以,在测试的过程中,逐渐培养系统设计能力,编码能力是很有必要的,这样我们才可以把问题控制在最初阶段,才能够避免在黑盒测试中的盲点被一直忽略。

  • linux link

    2007-11-28 16:57:18

    系统日志目录:/var/log/message.

    ##################################################

    SELINUX是Security Enhangcement Linux,非常安全系统,但对于新手来说,在配置一些东西的时候是个阻碍,通过以下步骤可以将其关闭:

    在/etc/selinux/config中设置/SELINUX=disabled

    在/boot/grub/munu.list中设置kernel/boot/vmlinuz-2.6.9ro root=/dev/hdal rhgb selinux=0

    执行命令sync后,重新启动机器。

    ##################################################

    在/boot/grub/munu.list中可以看到机器在启动时显示的一个或多个本机器安装的系统的版本信息。

  • 在VSFTPD的安装和配置过程和遇到的问题

    2007-11-28 15:31:41

    因为工作需要,搭建了一台vsftp服务器,步骤如下:

    1、在CentOS上安装系统自带的vsftpd:

    rpm -ivh --aid vsftpd-2.0.1-5.ElL4.3.i386.rpm

    不允许登录的用户记录在文件/etc/vsftpd.ftpusers和/etc/vsftpd.user_list中。

    2、启动vsftp服务:

    service vsftpd start

    3、在另一台机器上使用匿名登录到此文件服务器ftp 10.14.101.25:

    用户名使用anonymous, 密码随便,登录进去之后,可以下载文件,不能上传文件,ls, pwd可以使用,但不能切换到除/var/ftp/pub和/var/ftp之外的目录中。

    PS:目录/var/ftp/pub为FTP服务匿名用户登录的主目录。

    4、做了如下更改,希望能上传文件:

    修改/etc/vsftpd/vsftpd.conf文件:anon_upload_enable=YES.

    修改匿名用户的主目录的权限:chmod 777 /var/ftp/pub

    5、完成修改后,重新启动vsftpd服务,再次匿名登录,登录完即显示:refusing to run with writable anonymous root.

    问题一:VSFTP服务器是否不允许匿名用户上载文件。

    6、添加一个系统用户test,并使用此帐号登录到文件服务器,根据上述修改后,可以上传文件,下载文件和任意切换目录。ftp登录之后的用户主目录为/home/test.

    7、做如下更改和设置,希望改变test的用户主目录:

    在/etc/vsftpd/vsftpd.conf中将以下句子去掉注释或直接增加:

    chroot_list_enable=YES

    chroot_list_file=/etc/vsftpd.chroot_list

    user_config_dir=/etc/vsftpd_user_config

    重新启动文件服务器后,在本地新建文件/etc/vsftpd.chroot_list,将用户名test写入文件内容中;

    新建目录/etc/vsftpd_user_config后,在此目录下新建文件test,将local_root=/home/tmp.

    问题二:在做了上述修改后,使用test登录到服务器中,主目录变为根目录“/”,并且无法再切换目录了,将配置文件中的上述三行还原后,重启服务器,主目录又回到/home,并且可切换目录。为何?

     

     

     

     

  • 求助:软件评测师证书的登记页是作什么用的啊?

    2007-10-25 15:52:09

      拿到软件评测师的证书已经有几个月了,可是,证书后面的几页登记页是作什么用的啊,谁能告诉我!谢谢了!!
  • awk用法总结

    2007-09-10 16:08:50

    awk 用法:awk ' pattern {action} ' 

    变量名 含义
    ARGC 命令行变元个数
    ARGV 命令行变元数组
    FILENAME 当前输入文件名
    FNR 当前文件中的记录号
    FS 输入域分隔符,默认为一个空格
    RS 输入记录分隔符
    NF 当前记录里域个数
    NR 到目前为止记录数
    OFS 输出域分隔符
    ORS 输出记录分隔符

    1、awk '/101/'               file 显示文件file中包含101的匹配行。
       awk '/101/,/105/'         file
       awk '$1 == 5'             file
       awk '$1 == "CT"'          file 注意必须带双引号
       awk '$1 * $2 >100 '       file 
       awk '$2 >5 && $2<=15'     file
    2、awk '{print NR,NF,$1,$NF,}' file 显示文件file的当前记录号、域数和每一行的第一个和最后一个域。
       awk '/101/ {print $1,$2 + 10}' file 显示文件file的匹配行的第一、二个域加10。
       awk '/101/ {print $1$2}'  file
       awk '/101/ {print $1 $2}' file 显示文件file的匹配行的第一、二个域,但显示时域中间没有分隔符。
    3、df | awk '$4>1000000 '         通过管道符获得输入,如:显示第4个域满足条件的行。
    4、awk -F "|" '{print $1}'   file 按照新的分隔符“|”进行操作。
       awk  'BEGIN { FS="[: \t|]" }
       {print $1,$2,$3}'       file 通过设置输入分隔符(FS="[: \t|]")修改输入分隔符。

       Sep="|"
       awk -F $Sep '{print $1}'  file 按照环境变量Sep的值做为分隔符。   
       awk -F '[ :\t|]' '{print $1}' file 按照正则表达式的值做为分隔符,这里代表空格、:、TAB、|同时做为分隔符。
       awk -F '[][]'    '{print $1}' file 按照正则表达式的值做为分隔符,这里代表[、]
    5、awk -f awkfile       file 通过文件awkfile的内容依次进行控制。
       cat awkfile
    /101/{print "\047 Hello! \047"} --遇到匹配行以后打印 ' Hello! '.\047代表单引号。
    {print $1,$2}                   --因为没有模式控制,打印每一行的前两个域。
    6、awk '$1 ~ /101/ {print $1}' file 显示文件中第一个域匹配101的行(记录)。
    7、awk   'BEGIN { OFS="%"}
       {print $1,$2}'           file 通过设置输出分隔符(OFS="%")修改输出格式。
    8、awk   'BEGIN { max=100 ;print "max=" max}             BEGIN 表示在处理任意行之前进行的操作。
       {max=($1 >max ?$1:max); print $1,"Now max is "max}' file 取得文件第一个域的最大值。
       (表达式1?表达式2:表达式3 相当于:
       if (表达式1)
           表达式2
       else
           表达式3
       awk '{print ($1>4 ? "high "$1: "low "$1)}' file 
    9、awk '$1 * $2 >100 {print $1}' file 显示文件中第一个域匹配101的行(记录)。
    10、awk '{$1 == 'Chi' {$3 = 'China'; print}' file 找到匹配行后先将第3个域替换后再显示该行(记录)。
        awk '{$7 %= 3; print $7}'  file 将第7域被3除,并将余数赋给第7域再打印。
    11、awk '/tom/ {wage=$2+$3; printf wage}' file 找到匹配行后为变量wage赋值并打印该变量。
    12、awk '/tom/ {count++;} 
             END {print "tom was found "count" times"}' file END表示在所有输入行处理完后进行处理。
    13、awk 'gsub(/\$/,"");gsub(/,/,""); cost+=$4;
             END {print "The total is $" cost>"filename"}'    file gsub函数用空串替换$和,再将结果输出到filename中。
        1 2 3 $1,200.00
        1 2 3 $2,300.00
        1 2 3 $4,000.00

        awk '{gsub(/\$/,"");gsub(/,/,"");
        if ($4>1000&&$4<2000) c1+=$4;
        else if ($4>2000&&$4<3000) c2+=$4;
        else if ($4>3000&&$4<4000) c3+=$4;
        else c4+=$4; }
        END {printf  "c1=[%d];c2=[%d];c3=[%d];c4=[%d]\n",c1,c2,c3,c4}"' file
        通过if和else if完成条件语句

        awk '{gsub(/\$/,"");gsub(/,/,"");
        if ($4>3000&&$4<4000) exit;
        else c4+=$4; }
        END {printf  "c1=[%d];c2=[%d];c3=[%d];c4=[%d]\n",c1,c2,c3,c4}"' file
        通过exit在某条件时退出,但是仍执行END操作。
        awk '{gsub(/\$/,"");gsub(/,/,"");
        if ($4>3000) next;
        else c4+=$4; }
        END {printf  "c4=[%d]\n",c4}"' file
        通过next在某条件时跳过该行,对下一行执行操作。


    14、awk '{ print FILENAME,$0 }' file1 file2 file3>fileall 把file1、file2、file3的文件内容全部写到fileall中,格式为
        打印文件并前置文件名。
    15、awk ' $1!=previous { close(previous); previous=$1 }   
        {print substr($0,index($0," ") +1)>$1}' fileall 把合并后的文件重新分拆为3个文件。并与原文件一致。
    16、awk 'BEGIN {"date"|getline d; print d}'         通过管道把date的执行结果送给getline,并赋给变量d,然后打印。 
    17、awk 'BEGIN {system("echo \"Input your name:\\c\""); getline d;print "\nYour name is",d,"\b!\n"}'
        通过getline命令交互输入name,并显示出来。
        awk 'BEGIN {FS=":"; while(getline< "/etc/passwd" >0) { if($1~"050[0-9]_") print $1}}'
        打印/etc/passwd文件中用户名包含050x_的用户名。

    18、awk '{ i=1;while(i<NF) {print NF,$i;i++}}' file 通过while语句实现循环。
        awk '{ for(i=1;i<NF;i++) {print NF,$i}}'   file 通过for语句实现循环。    
        type file|awk -F "/" '
        { for(i=1;i<NF;i++)
        { if(i==NF-1) { printf "%s",$i }
        else { printf "%s/",$i } }}'               显示一个文件的全路径。
        用for和if显示日期
        awk  'BEGIN {
    for(j=1;j<=12;j++)
    { flag=0;
      printf "\n%d月份\n",j;
            for(i=1;i<=31;i++)
            {
            if (j==2&&i>28) flag=1;
            if ((j==4||j==6||j==9||j==11)&&i>30) flag=1;
            if (flag==0) {printf "%02d%02d ",j,i}
            }
    }
    }'
    19、在awk中调用系统变量必须用单引号,如果是双引号,则表示字符串
    Flag=abcd
    awk '{print '$Flag'}'   结果为abcd
    awk '{print  "$Flag"}'   结果为$Flag

  • 好链接要留着

    2007-08-10 12:16:18

    ftp://ftp.freshrpms.net/pub/freshrpms/redhat/9
  • 在CentOS下安装小企鹅输入法fcitx

    2007-08-10 10:26:50

    在CentOS下安装小企鹅输入法:

    一、CentOS的版本:
    [candy@localhost xinput.d]$ cat /etc/redhat-release
    CentOS release 4.2 (Final)

    二、从下载小企鹅输入法的链接地址:
    http://www.fcitx.org/main/?q=node/9
    下载稳定版:fcitx-3.1.1-bin.tar.bz2

    三、解压:#tar -xjvf fcitx-3.1.1-bin.tar.bz2

    四、安装:
    #cd ./fcitx-3.1.1-bin
    #./fcitx.install

    五、将/etc/X11/xinit/xinput.d/zh_CN文件的内容改为:
    XIM=fcitx

    XIM_PROGRAM=fcitx

    GTK_IM_MODULE=fcitx

    gnome-im-settings-daemon >/dev/null

     六、配置环境变量
    在/etc/profile文件或者在/etc/bashrc文件中增加如下两行:
    export LC_CTYPE="zh_CN"
    export XMODIFIERS="@im=fcitx"

    七、输入命令fcitx即可启动,使用ctrl+空格键激活。
  • 软件测试需要开发经验

    2007-07-19 16:45:33

      做初级测试工程师的工作已经一年了,感觉要学的东西太多,一年来东打一枪,西打一炮,感觉什么都没有学到,工作也逐渐没有了挑战性。

      每个人都说,做测试需要开发经验,那我没有开发经验,是不是有必要先转行去做两年开发,再回过头来做测试呢。

      困惑中。

  • 手机丢了

    2007-03-01 13:40:40

    手机丢了

    无语

  • 成人的世界,小孩怎么会懂?

    2007-02-28 15:49:54

     

      昨晚睡觉前,闲来无事,我学着武林外传里面小郭姐姐的样子,说着“世界如此美好,我却如此烦燥,这样不好,不好”。被12岁的豆豆看到之后,居然跟我说“姐姐我好羡慕你哦,我觉得你每天很开心,无忧无虑的样子,也没有什么扰心的事”,她的这句话,真是让我觉得又好气又好笑!

      成人的世界,小孩子怎么会懂。自从跨过23岁的门坎,我已经开始几度忧思几许愁了。我一直觉的中国人民的三座大山依然存在的,那就是房子,子女教育和疾病。我开始想有个家了,可惜。。。;我开始感觉到工作的压力了;我开始担心多少岁才能当上妈妈;我担心什么时候有自己的家,自己的大大大房间;我开始担心三十岁以后会不会失去竞争力;我甚至开始担心老妈年纪越来越大,会不会有一天像外婆那样多种疾病缠身。我同样也开始担心自己的身体健康,可能是我的担心有点多余,但我觉不是一个90后的儿童眼中的那样无忧无虑。

      小孩子的世界,我们都经历过,也懂。可是我们除了继续和他唠叨一些自以为是为他们好的话,并且里面夹杂了多少人生经验,还能做些什么呢。而且这些我,我们小时候也听过,还曾经觉得这种假大空的话真烦。我知道现在的小孩对这些话也是这种感觉,可是我仍然无法让他们真正地听进去。我们除了严格管着他们,教育他们之外又还能做什么呢,如果他们左耳进右耳出,那只好多重复几遍就是了,也许他们长大了,也会说,小时候听说就好了。都是这样的轮回吧。

      小孩烦的无非是学习的压力和可以玩的时间太少。可是他们又可曾知道90后出生的小生在我们眼里是多么幸福啊。其实我的妹妹的压力应该是同辈人中最少的。因为他们只是上小学而已,没有参加任何培训班和特长班。不像有些小孩子为了上人大附中,考英语三级,上奥数班还要考级。结果他们每天都为学习的任务太多而发愁。小孩子的世界,我们应该如何改变?

      我能够理解他们,我小时候也是这样,学习平平,从来没有给过自己压力,只是一味的抓住一切机会玩,不过玩得也平平。那个时候,我妈妈上班工作,我丝毫不觉得好辛苦,只觉得她好幸福,没有作业,殊不知工作比学习更难,而小时候的我却以为和穿衣吃饭一样简单,如今好多事情回过头都想明白了,那是因为,我不再是小孩。

     

  • 缺陷探测率DDP的计算方法

    2007-02-27 12:13:55

    缺陷探测率DDP的计算方法如下:

    DP=Bugstester/Bugstester+ Bugscustomer
      其中,Bugstester为测试者发现的错误数;
      Bugscustomer为客户发现并反馈技术支持人员进行修复的错误数。

  • 打气球,吹气球,真的是一种体力活,当然也是一种年味

    2007-02-16 23:47:49

    明天就是大年三十了,刚才和妹妹们一起奋斗了好久,胳膊酸了,手指被勒疼了,看着满地的气球,傻傻地笑了。

    不知不觉中来北京已经两年多了,今天突然对气球也产生了感情,不知不觉中满地的所球已经悄然进入了我的内心世界,触动了心中某个很柔软的角落。本是因为北京禁放鞭炮,而人们却无法释怀那辟哩叭啦的鞭炮声,而去打了,吹了满地的气球,待新年钟声敲响的那一课,使劲的用脚踩出向往已久的声音,踩出除旧迎新的喜悦,踩出一个好彩头。可是在解除对鞭炮的禁令之后,踩气球亦成为了一个传统,成为了一种可能会存在于人们记忆中挥之不去的年味。尤其是对于现在的不轻易感到自己幸福开心的小孩子们。

    记忆中,小时候的年味是门神,福字,对联,我们还把小方纸剪出来贴到桌子腿上之类的地方;小时候的年味是一年盼到头的新衣服,是一年盼到头的那吃的,一头扎进自家做的糯米糖饼,自家酿的水酒,自家炸的肉丸子,自家炒的瓜子花生,自家腌的咸鱼腊肉。。。。。。

    现在对于衣服吃的之类自然是毫无知觉了,在这个温饱已然解决的年代,人们的精神世界似乎越来越空虚,在这个各种旅游,各种娱乐充斥着人们生活的年代,人们的精神渴求似乎越来越不能够被满足,今天,在放下一身的疲惫,结束了春节前最后一天的工作,在生产气球的过程中,居然又滋生出某种已经久违了的情愫。原来人其实是很容易产生感情的,尤其是对长期隐藏在生活中的一些细枝未节。

    只是出了一身汗,手指因为要系扣到现在仍然生疼,但是可以肯定的是,本来已经对新年麻木的一颗心,由气球带来的盎然生机,对新年又生出了一种喜庆的渴望,今天可以带着对明天的期盼微笑着睡个好觉了。

  • 07年软件测试评测师的考试已经过了报考时间吗

    2007-02-16 11:03:56

    真是挺郁闷的,刚才上软考网没有找到软件评测师的报考时间和方法,只是在某个贴子中看到什么报考时间已经过了这句话,大概是二月初就已经过了考试时间

    可是我还于上个月傻傻的买了本书,准备好好地看一下,并且去参加下半年的考试呢,也是于今天才知道,只有上半年才安排评测师的考试,可是其他的师们的考试都有一年两次的机会,是因为参加评测师考试的人太少吗

    考试时间是安排在5月26日了,不知道还有没有补报的机会

    报考时间真的过了吗?

  • 望眼欲穿的年终奖终于。。。。。。

    2007-02-15 15:58:13

      早在一个月以前,就肯定自己应该会有年终奖的吧,于是,该买的买,该花的花,结果眼瞅着时间一天一天的过去,公司依然是毫无动静,让我奇怪的是公司所有的人都好像工作是第一位的,从来不关心此事,可是我的心已经提到半空中放不下来了,于是我厚着脸皮问了一下我们公司的前台,说是应该会有吧,可能会发得比较晚。

      虽然得到这样的答复,可是内心一直在期盼。今天上午,神龙见尾不见首的老总又回公司了,并且大家都被一个接一个地被叫进去,想来定是发年终奖无疑了,于是时刻准备着被叫到老总办公室,结果一上午过去了,看来此项活动已经结束,已然是没有我的份。

      中午暗自安慰了自己半天,反正在公司还没有工作满五个月呢,不给也是应该的,更何况,刚刚转行步入软件测试,最重要的是适应和学习,实践和思考,目前的待遇那都是次要问题,笑到最后才能笑得最好。

      可是虽然中午已经同意,年终奖,这是一个次要问题,可是这必竟是关于温饱问题的大事啊,俗话说,一分钱难死英雄好汉,眼看着我就要用所剩不多的钱来过这个本命年的春节,就感觉毕业都快四年了,怎么混得这么差,别人都买房结婚生子了。于是,就想到是不是因为自己表现不好所以没有啊,等等,不会等来年就被开了吧,本来一直听说本命年会比较特别,我不会背运吧。

      于是厚着脸皮到人事打听,原来是十月一日之后到岗的人员一律没有,我比所订日期晚了七天,长吁一口气之后,又开始自责起来。我何时变得这么市侩,难道真的是感觉到生活的压力了。我曾经不止一次的告诉自己只要每天好好工作,好好学习,一天一点提高,钱,那是自然而然就来到你身边了。更让我汗颜的是有个小伙子,也是和我差不多时候来的,人家就完全不把这当一回事,看来是我在工作上的心思没有足够地专心了。

      看到很多的测试同仁,他们都很强,我想自己只要朝着一定的方向努力就行了,只是步入测试这一行之后,才发现要学的东西多如牛毛,真的是不好定位发展方向,只能尽人事,听天命了。

  • RFC3261文档中文翻译尝试中

    2007-02-15 12:16:32

    (公司的产品新增加了对SIP的测试功能,在工作这余对其的学习效果甚是不佳,为了不再在看RFC3261时昏昏欲睡,突发其想,边看边翻译下来,能否坚持就是个未知数了,不过也算了却了长时间以来希望开通一个个人空间用于工作日志的心愿。各位前辈看到了理解不对的地方恳请指出来)

    一、介绍

      许多网络应用都需要创建和管理会话,这儿所说的会话指的是一个连接中参与者之间的数据交换。这些网络应用的执行会因为参与者的实践活动变得复杂。同一个用户可能会使用不同的终端,他们可能有多个网络地址,而且他们可能会在与其他用的交流中使用多种不同的媒体,有时候是同时使用。许多网络协议都被授权可以在通信中传输含有多种不同形式的实时多媒体数据的会话数据,比如包括声音文件,视频文件或者文本消息。网络会话初始化协议(SIP)通过使网络终端(也称用户代理)能够发现其他用户并且使他们对需要共享的会话的描述能够达成共识来和这些网络协议一起工作。为了定位预期会话的参与者和一些其他的功能,SIP能够在网络主机(也就是代理服务器)上创建下层组织结构使用户代理可以发送注册请求,邀请请求和其他一些请求。SIP是一个敏捷地,目标单一地用于创建,修改和终止会话的网络工具,它相对于下层的网络协议是独立的,并且与所创建的会话的类型没有依赖关系。

    2、SIP功能点汇总

      SIP是一个应用层的控制协议,可以用来创建,修改和终止多媒体会话(会议)比如说网络电话。SIP也可以邀请参与者参加一个已经存在的会话,比如说多人会议。媒体可以被添加到一个已经存在的会话(或者是从中移除)。很显然,SIP支持域名映射和重定向服务,它的支持使个人更加灵活,用户可以不关注具体的网络位置而只是使用一个简单而且直观的唯一标识。

      SIP在创建和终止多媒体的通信中支持以下五个方面的功能:

      用户定位: 检查终端系统,用于通信。

      用户有效性: 检查参与者参加通信的意愿程度。

      用户能力: 检查用于通信的媒体和媒体参数。

      建立会话: “ringing”,建立呼叫方和被呼叫方的的会话参数。

      会话管理: 包括会话的传送和终止,修改会话的参数和调用服务。

      SIP不是一个垂直集成的通信系统。SIP更适合于被叫做一个部件,它可以与其他的IETF协议一起使用来组成完整的多媒体架构。这些架构将会包括一些典型的协议,比如实时传输协议RTP(RFC1889 [28])用于实时传输数据和提供QoS反馈,实时流协议RTSP(RFC2326[29])用于控制流媒体的传输,媒体网关控制协议MEGACO(RFC3015[30])用于控制公共交换电话网PSTN的网关,还有会话描述协议SDP(RFC2327)用于描述多媒体会话。因此,SIP应该和其它协议一起协作来为用户提供完整的服务。但是,SIP的基本功能和操作不需要依赖任何其它的协议。

      SIP不提供服务。进一步说,SIP提供的是用于执行其它服务的基础。例如,SIP可以定位一个用户并且把一个封装好的实例传送到他的当前位置。假设这个基础被应用于传送SDP所写的会话描述,用户终端可以对会话参数达成共识。如果像传送会话描述一样使用这个基础传送呼叫方的照片,那这个“呼叫ID”的服务也可以很容易的被执行。正如这个例子所表明的那样,提供一个简单的基础用于多种不同服务的执行。

      SIP不提供会议控制服务,比如议席控制或投票系统,并且不会去规定如何安排一个会议。SIP可以被用于初始化一个使用其它会议控制协议的会话。虽然由SIP创建的消息和会话可以跨越完全不同的网络,但是SIP不能,也不会提供预留任何类型的网络资源的能力。

      所提供的这些服务的特征使得安全显得格外地重要。所以,SIP提供了一系列的安全措施,包括防止拒绝服务,用户与用户之间和用户与代理之间的认证,完整性保护和加密隐私保护。

      SIP可以基于IPv4,也可以基于IPv6工作。

    3、术语 (略)

    4、操作总汇

      这个小节将通过简单的例子来介绍SIP的基本操作,是很自然的向导语言而非标准的陈述。

      第一个例子说明了SIP最基本的功能:定位一个终端,发出通信请求,通过协商会话参数来建立一个会话,终止已被建立起来的会话。

      图一表明的是一个SIP消息如何在两个用户艾丽丝和鲍勃之间进行交换的典型的例子。(每条消息都是由字母“F”和一个指向正文的数字来共同做为标记的)。在这个例子中,艾丽丝使用在她的PC机上安装的一个SIP应用(也就是图中所标明的一种电话软件)通过因特网呼叫鲍勃的SIP电话。图中也表明了两个在会话建立时必须的设备:两个SIP代理服务器,分别代表艾丽丝和鲍勃。图一中由虚线组成的几何图形所表明的典型布局就是经常被提出来说的“SIP梯形”。

      艾丽丝通过鲍勃的SIP标识来呼叫他,所谓的SIP标识其实是统一资源标识符URI的一种,在此被称为SIP URI。SIP URI的定义详见19.1小节。它和电子邮件地址有点类似,含有用户名和主机名。所以鲍勃的SIP URI是bob@biloxi.com,biloxi.com这个域名就是鲍勃的SIP服务提供商。艾丽丝拥有的SIP URI是alice@atlanta.com.艾丽丝可能需要输入鲍勃的URI,或者是点击一个超级链接,或者是点击地址本上的一个条目。SIP也提供一个安全URI叫作SIPS URI。比如sips:bob@biloxi.com。对SIPS URI的呼叫可以保证所有的SIP消息可以安全,保密地从呼叫方传送到被呼叫方。所以,请求虽然可以安全地送到被呼叫方,但是保密机制是依赖于被呼叫方所属域的政策的。

      SIP是基于类似于HTTP的请示/响应的传输模式的。每个传输都包含了调用了某种特殊方法或者是功能的请求,并且最少有一个来自于服务器的响应。在这个例子中,传输由艾丽丝的电话软件给鲍勃发出INITE请求开始。INVITE请求是SIP的一种方法,指的是发出请求者(艾丽丝)希望服务器(鲍勃)进行响应。INVITE请求在报头域含有一个数字。报头域是给一个消息提供附加信息的一种属性。INVITE请求中包含一个唯一地呼叫标识,目标地址,艾丽丝的源地址和关于艾丽丝希望与鲍勃建立的会话的类型的信息。INVITE请求如图一中F1消息所示:

                atlanta.com  . . . biloxi.com
                     .      proxy              proxy     .
                   .                                       .
           Alice's  . . . . . . . . . . . . . . . . . . . .  Bob's
          softphone                                        SIP Phone
             |                |                |                |
             |    INVITE F1   |                |                |
             |--------------->|    INVITE F2   |                |
             |  100 Trying F3 |--------------->|    INVITE F4   |
             |<---------------|  100 Trying F5 |--------------->|
             |                |<-------------- | 180 Ringing F6 |
             |                | 180 Ringing F7 |<---------------|
             | 180 Ringing F8 |<---------------|     200 OK F9  |
             |<---------------|    200 OK F10  |<---------------|
             |    200 OK F11  |<---------------|                |
             |<---------------|                |                |
             |                       ACK F12                    |
             |------------------------------------------------->|
             |                   Media Session                  |
             |<================================================>|
             |                       BYE F13                    |
             |<-------------------------------------------------|
             |                     200 OK F14                   |
             |------------------------------------------------->|
             |                                                  |

             图一: 使用SIP梯形示例的SIP会话的创建

          INVITE sip:bob@biloxi.com SIP/2.0
          Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bK776asdhds
          Max-Forwards: 70
          To: Bob <sip:bob@biloxi.com>
          From: Alice <sip:alice@atlanta.com>;tag=1928301774
          Call-ID: a84b4c76e66710@pc33.atlanta.com
          CSeq: 314159 INVITE
          Contact: <sip:alice@pc33.atlanta.com>
          Content-Type: application/sdp
          Content-Length: 142

          (Alice's SDP not shown)
    上面文本消息的第一行包含了方法名INVITE。后面跟着的是报头域的内容。这个例子中报头域的内容只包括了必需的最少内容。以下简单介绍一下报头域的内容:

      Via部分包括了艾丽丝希望能够对她的请求进行回复的地址:pc33.atlanta.com.同时有一个分支参数做为此次传输的标识。

      To部分包含了一个显示名(鲍勃)和该请求直接指向的一个SIP或者SIPS URI(sip:bob@biloxi.com)。显示名的描述详见 RFC 2822 [3]。

      From部分也包含了一个显示名(艾丽丝)和这个请求发起者的一个SIP或者SIPS URI(sip:alice@atlanta.com)。这个报头域同时还包含一个由电话软件增加到URI上的一个随机数(1928301774)做为标记。增加这个标记的目的是为了辨别身份。

      Call-ID包含一个由随机数和电话软件所在的主机名或IP地址所生成的全球唯一标识来做为此次呼叫的标记。由TO部分,FROM部分的tag,再加上Call-ID就可以完全定义艾丽丝和鲍勃之间的端到端的SIP关系和其所指向的对话。

      CSeq或者Command部分包括一个整数和一个方法名。当这个对话中每增加一个新的请求,这个整数值也会增加,这个整数也就是递增的序列号。

      Contact域包含的SIP或者SIPS URI表明的是艾丽丝直接连接的路由器,这个用户名通常由完全限定域名FQDN组成。一旦FQDN被选定,但是许多终端用户没有注册域名,所以IP地址是可选的。Via域表明的是响应是从哪发出的,而Contact域表明的是后续的请求将从哪发出。

      Max-Forwards域中包含的数值是请求到达目的地过程中转发次数的限额,每转发一次,他的值会减一。

      Content-Type中包含的是对消息正文的描述。(此范例中没有给出消息正文)。

      Content-Length中包含的是由字节表示的消息正文的长度。

      对于SIP报头域的完整定义详见第20小节。

      关于会话的细节,如媒体类型,多媒体数字信号编解码器,采样率,均没有在SIP中被描述出来。但是在SIP消息的正文中包括由其它协议格式编码的对会话的描述。其中一种格式就是会话描述协议SDP(RFC 2327 [1])。这个SDPI消息,在示例中没有给出,是通过SIP传送出去的,类似于电子邮件中的文本附件或HTTP消息中的网页信息。

      因为电话软件不知道鲍勃的地址或biloxi.com域的SIP服务器的地址,所以电话软件将邀请信息发给艾丽丝的所在的域atlanta.com的SIP服务器。域atlanta.com的SIP服务器的地址可以在艾丽丝的电话软件中配置,也可以被其DHCP发现。

      atlanta.com域的SIP服务器是一种SIP代理服务器。SIP代理服务器收到SIP请求并把他们转发到相应的被请求者那。在这个例子中,代理服务器收到INVITE请求并将100(trying)的响应回发给艾丽丝的电话软件。100(trying)的响应表明代理服务器已经收到INVITE信息并且正在于目标地址联系。SIP的响应消息由三个数字和一个描述性的短语组成。这个响应消息和INVITE请求含有一样的TO, From, CALL-ID, CSeq部分的内容和Via部分的分去参数,这样艾丽丝的软件就可以将此响应与所发的邀请请求联系起来。atlanta.com域的代理服务器通过特定的DNS(域名服务)找到biloxi.com域的代理服务器。这样,它能够得到biloxi.com域的代理服务器的IP地址,然后将INVITE请求转发到那。在转发请求之前,atlanta.com域的代理服务器在Via报头域增加了一个值为自己的地址的附加参数(INVITE请求已经在原始的Via域包含了艾丽丝的地址)。biloxi.com域的代理服务器收到了这个INVITE请求,并且回发了一个100(trying)的响应表明他收到了请求并且正在处理中。代理服务器需要查询数据库,这就量通常所说的地址服务,里面包括了鲍勃现在的IP地址。(我们可以在下一个单节中看到这种数据库是怎么回事。)biloxi.com域的代理服务器增加自己的IP地址到INVITE请求中的另一个Via报头域,然后再发给鲍勃的SIP电话。

      鲍勃的SIP电话收到这个INVITE请求,并且通过响铃的方式通知鲍勃有一个艾丽丝打来的电话,是否接听。鲍勃的SIP电话将上述处理过程通过180(Ringing)表明并使用那两个代理服务器反方向发回。每个代理服务器通过Via报头域决定将这个响应发到哪并且从上往下依次去掉自己的IP地址。所以,虽然在初始发出INVITE请求的时候需要DNS和地址服务,但是在180(Ringing)响应确不需要查询或者代理服务器保持状态就可以被返回到呼叫者处。当艾丽丝的电话软件收到这个180(Ringring)的响应时,他可能通过响铃或者通过在艾丽丝的屏幕上显示消息的方式来通知艾丽丝。

      在这个例子中,鲍勃决定接起这个呼叫。当他拿起话筒的时候,他的SIP电话发出一个200(OK)的响应来表明这个呼叫被接起。这个200(OK)的响应包含了一个关于鲍勃希望与艾丽丝建立的会话的类型的SDP媒体描述的消息体。这个两段交换提供了基本的协商兼容特性并且是基于一个简单的提出/响应模式的SDP交换。如果鲍勃不想接听电话或者电话占线,一个错误响应就会代替正常的200(OK)发出,这样的话,任何类型的媒体会话都不会被建立。完整的SIP响应代码详见21小节。这个鲍勃发出的200(OK)的响应(也就是图一中的第9个消息)可能是这样的:

       SIP/2.0 200 OK
          Via: SIP/2.0/UDP server10.biloxi.com
             ;branch=z9hG4bKnashds8;received=192.0.2.3
          Via: SIP/2.0/UDP bigbox3.site3.atlanta.com
             ;branch=z9hG4bK77ef4c2312983.1;received=192.0.2.2
          Via: SIP/2.0/UDP pc33.atlanta.com
             ;branch=z9hG4bK776asdhds ;received=192.0.2.1
          To: Bob <sip:bob@biloxi.com>;tag=a6c85cf
          From: Alice <sip:alice@atlanta.com>;tag=1928301774
          Call-ID: a84b4c76e66710@pc33.atlanta.com
          CSeq: 314159 INVITE
          Contact: <sip:bob@192.0.2.4>
          Content-Type: application/sdp
          Content-Length: 131

          (Bob's SDP not shown)

      这个响应的第一行包含响应代码200和原因OK。其它的行都是报头域。Via, To, From, CALL-ID和CSeq报头都是从INVITE请求中拷贝过来的。(在这儿,有三个报头域的值……一个是艾丽丝的SIP电话加上去的,一个是atlanta.com域的代理服务器加上去的,再有一个就是biloxi.com域的代理服务器加上去的。)鲍勃的SIP电话在To报头域增加了一个标志参数。这个标志将被参加对话的每个终端使用,也将被这个呼叫中后续的的请求和响应中使用。Contact报头域中包含了一个鲍勃可以通过SIP电话直接方问的URI。Content-Type和Content-Length域中的内容指向的是鲍勃的SDP媒体信息的消息体(在此没有给出)。

      除了本示例中的DNS和地址查询服务,代理服务器还可以灵活的决定把响应发到哪的路由。比如,如果鲍勃的SIP电话返回的是一个486(现在忙)的响应,biloxi.com域的代理服务器可能会把INVITE请求发到鲍勃的语音邮件的服务。一个代理服务器也可以同时将一个INVITE请求发送到一系列地址上去。这个并行的寻址就是所谓的分流。

      在这种情况下,200(OK)的响应通过这两个代理服务器返回,艾丽丝的电话软件收到后就停止了响铃以表明此次呼叫被接起。最后,艾丽丝的电话软件发出一个确认消息ACK到鲍勃的SIP电话上去确认这个通话前最后的响应。在这个例子中,ACK直接从艾丽丝的电话软件发送到鲍勃的SIP电话,没有经过那两个代理服务器。这是因为两个终端都从INVITE请求和200(OK)的Contact报头域知道了对方的地址,这在初始化INVTITE请求的时候是互相不知道的。代理服务器的查询功能再也不需要了,所以代理服务器被踢出了这个呼叫流。通过INVITE请求、200响应和ACK确认的三次握手,SIP会话建立起来了,完整的建立会话的细节详见第13小节。

       现在艾丽丝和鲍勃的媒体对话开始了,他们所发送的媒体包的格式是在SIP的交换中得到双方认可的。一般来说,端到端的媒体包和SIP信号消息流采用的是不一样的路径。

      在此次会话中,艾丽丝和鲍勃都可以决定是否改变此次媒体对话的类型。这个可以通过发送一个包含新的媒体描述的re-INVITE请求来完成。这个re-INVITE请求指向的是这个已经存在的对话所以其他的参与者可以知道是修改一个已经存在的会话而不是创建一个新的会话。其它的参与者可以发送一个200(OK)的响应来接受这个改变。发出请求者可以发出一个ACK来响应这个200(OK)。如果其他参与者不接受这个改变,他可以发出一个错误的响应比如说488(这儿不接受),当然这个响应发出后也需要收到一个返回过来的ACK.然而,re-INVITE的失败并不会导致已经存在的这个呼叫的失败,会话将按之前协商好的类型继续。关于会话修改的完整细节详见第14小节。

      在这次呼叫的最后,鲍勃先断线(挂断话筒)并且发出一个BYE消息。这个BYE消息直接发送给艾丽丝的电话软件,同样没有经过代理服务器。艾丽丝发出一个200(OK)的响应来确认这个BYE消息。然后此次会话和BYE的传输都结束了。这儿不需要发出ACK,只有在响应对INVITE请求的响应时才需要发出ACK.关于对INVITE的这种特殊处理的原因我们稍后再谈,但是它会影响到SIP的可靠机制,包括电话被响应和分流发出的时间。所以,SIP中对请求的处理经常将他们分为INVITE类和除INVITE之外所有的方法归为的non-INVITE类。关于结束对话的完整细节详见第15小节。

      第24.2小节完整地描述了图一中的消息。

      在某些情况下,代理服务器在整个会话周期中通过原来的SIP信息流的路径看到所有终端之单的消息是很有用的。比如,biloxi.com域的代理服务器希望在SIP信息流的路径上看到除初始的INVITE请求这外的SIP消息流,他就可以在INVTE请求中加入一个路由请求报头域Record-Route,其中包含了一个URI直接指向这个代理服务器的主机名或IP地址。这个信息可以被鲍勃的SIP电话收到,并且因为Record-Route报头域会被200(OK)的响应返回,那么艾丽丝的电话软件也可以收到这个信息,并且双方都会在整个通话过程中将其保存。每个代理服务器都可以自主地决定是否接收后续的消息,这些消息将经过所有选择接收他们的代理服务器。这个特性通常被应用在需要提供mid-call功能的代理服务器上。

      注册是SIP的另一个普遍的操作。通过登记的方法,biloxi.com域服务器可以知道鲍勃现在的地址。鲍勃的SIP电话会周期性地将注册消息发送到biloxi.com域中的SIP注册中心的服务器上。这个注册消息把鲍勃现在登录的机器与SIP URI或SIPS URI(sip:bob@biloxi.com)联系起来。(通过Contact报头域传送SIP URI或SIPS URI)。注册中心将这个联系,也称为绑定,写到一个biloxi.com域服务器可以使用的数据库里面,这就是所说的地址服务,通过注册服务器和域代理服务器是同一台机器。所以这儿有一个重要的概念,那就是这些SIP服务器类型的区别是逻辑上的而不是物理上的。

      鲍勃不会局限于只注册一个设备。比如,他家里的和办公室里的SIP电话都可以发出注册消息。这些消息都被地址服务存放到一起,并且代理服务器可以通过不同类型的查找来定们鲍勃。同样的,多个用户可以在同一台机器上同时发出注册消息。

      地址服务只是一个抽象的概念。通常指的是包含一些信息,使得代理服务器可以通过输入一个URI后收到零个或多个URI来告诉它将这个请求发向哪儿。注册不是唯一的创建这些信息的方法,只是其中的一种。管理员可以配置一对一的映射功能。

      最后,在SIP中有一个重点,注册只是用来决定收到的SIP请求的路由但是不负责授权这些发出的请求。授支和认证是基于请求/应答的机制和上下文的请求来处理的,或者通过一个底层的支持来实现,这些将在第26节中讨论。

       在这个例子中的关于注册的完整设置详见第24.1小节.

       在SIP中的另外一些操作,比如查询一个SIP服务器的能力,客户端的选项,取消一个已经发出的请求,都会在以后的章节中介绍.

    5 协议的结构

      SIP是一种分层结构的协议,所以他的行为描述根据的是一组相对独立,关系松散的进程。对协议的行为进行分层描述是为了更好地进行表达,并且允许在一个单独的小节中对公共的功能进行描述。它不会指明一个具体的实现。当我们说到一个因素“包含”一个层,我们指的是它符合这个层所定义的规则。

      并不是每个因素都被指定包含协议中的每个层。进一步地说,SIP中指定的因素是逻辑上的而不是物理上的。一个物理的实现可以选择不同的逻辑因素,可能仅仅是基于串行传输的。

      SIP中的最低层是语法和编码。它的编码指定使用的是扩展的Backus-Naur Form语法(BNF)。完整的BNF将在第25小节中闸述。第7小节中可以预览到SIP消息的整个结构。

      第二层是传输层。它定义了一个客户端如何在网络上发送请求并且接收响应和一个服务器端如何收到请求并且发出响应。所有的SIP因素都包含了一个传输层。关于传输层将在第18小节中被描述到。

      第三层是事务层。事务是SIP的基本组成部分。一个事务包括一个由客户端事务(通过传输层)发到一个服务器事务的请求和所有从服务器事务返回到客户端的针对这个请求的所有响应。事务层处理应用层的重发,匹配响应与请求和应用层的超时。用户代理客户端UAC完成的任何任务都是建立在一系列的事务之上的。关于事务的讨论详见第17小节。用户代理和有状态代理都包含一个事务层。但是无状态的代理不包含事务层。传输层包含一个客户端组件(也就是客户端事务)和一个服务器组件(也就是服务器事务),每个代表有限的状态机,它被构造来处理特定的请求。

      事务层之上的是事务用户TU。每个SIP实例,除了无状态代理,都是一个事务用户。当一个TU准备发出一个请求时,他创建一个客户端事务实例并且和目标IP地址,端口,接收设备一齐发出。一个TU可以创建一个客户事务也可以取消掉。当一个客户端取消一个事务时,它请示服务器停止未完成的处理,返回到事务初始化前的状态,并且产生一个指的错误代码给这个事务。这样CANCEL请求就完成了,它由自己的事务组成,但是所指向的事务却被取消了(详见第9小节)

      这些SIP的因素,包括,用户代理客户端,服务器端,无状态代理、有状态代理和注册员,都包含一个用以与其它因素区分的核心。这些核心,除了无状态代理,都是一个事务用户。当然UAC和UAS的核心依赖于他们的方法,第8小节中描述的是所有方法的一些公共规则。UAC的规则负责请示的建立,UAS的规则负责请求的处理和响应的产生。因为注册中心在SIP中扮演的是一个重要角色,处理注册服务的UAS都有一个特殊的名字,注册员。第10小节中将描述UAC和UAS在实现注册服务时的核心行为。第11小节描述UAC和UAS在实现可选服务时的核心行为,这将决定一个UA的能力。

      在对话中肯定会有其它请求会被一起发出。对话是指在两个用户代理之间保持一段时间的端到端的SIP关系。对话要求在两个用户代理之间有顺序的消息和正确的路由。在这个规范中,INVITE请求是建立一个对话的唯一地方法。当一个UAC发出的请求包含对话内容的话,他不但遵循第8节中讨论的公共规则而且遵循对话请求的规则。第12小节讨论对话及创建和维护对话,包括对话中请求的创建的程序。

      SIP中最重要的方法是INVITE方法,它是用来在参加者之间创建一个会话的。一个用于交流目的的会话是由参加者,参加者之间的媒体流组成的。第13小节中讨论的是一个或一组SIP对话的初始化过程。第14小节讨论的是在对话中如何使用INVITE请求来改变会话的特征。最后,第15小节讨论了如何终止一个会话。

      第8, 10, 11, 12, 13, 14, 和 15小节是完整的UA核心的过程。第9小节描述的是UA核心和代理核心都有的取消过程。第16小节讨论的是代理因素,代理要求在用户代理之间有消息的正确路由。

      6 定义

      以下列出的是SIP中的术语:

      记录地址(Address-of-Record): AOR是指向一个定位服务器的SIP或SIPS的URI,它可以将URI映射到用户的具体位置。通常情况下,定位服务是通过注册中心来完成的。AOR经常被认为是用户的公共地址。

      背对背的用户代理(Back-to-Back User Agent): 背对背的用户代理B2BUA是一个像UAS一样接收请求并且对其进行处理的逻辑实体。为了决定如何应答收到的请求,它得像一个用户代理客户端UAS一样发出请求。与代理服务器不同的是,它需要保持对话状态,并且参预到所建立对话的所有请求中。因为他是一个UAC和UAS的串联系统,所以不需要对它的行为进行额外的定义。

      呼叫(CALL):呼叫是指终端之间的一些交流的非正式术语,通常用来建立多媒体会话。

      对话(Call Leg):对话的别名。本规范中没有使用。

      请求有状态的(Call Stateful):如果一个代理在对话中从初始化INVITE请求到结束BYE请求都保持其状态的话,我们就称其为请求有状态的代理。一个请求有状态的代理肯定是事务有状态的,而反过来,事务有状态的不一定就是请求有状态的。

      客户端(client):客户端可以是发出SIP请求和接收SIP响应的任何网络元件。客户端可能是直接和用户交流的,也可能不是。用户代理客户端和代理服务器也是一种客户端。

      会议(Conference):是一种有多个参加者的多媒体会话(session),后面有对会话的定义。

      核心(Core):核心是对不同类型的SIP实体的功能进行区分。比如,可心指定一个有状态的代理或者无状态的代理,一个用户代理或者是一个注册员。所以的核心,除了无状态的代理,都是一个事务用户。

      对话(Dialog):一个对话是指在两个UA之间能保持一段时间的端到端的SIP关系。一个对话是建立在SIP消息之上的,比如,对一个INVITE请求会有一个2xx响应。一个对话是由呼叫ID,本地标志和远端标志来唯一确定的。对话在RFC2543中被正式地称为Call leg。

Open Toolbar