??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲色婷婷综合久久,久久强奷乱码老熟女网站,高清免费久久午夜精品http://www.shnenglu.com/doing5552/记录每日ҎQ不枉h生一?/description>zh-cnWed, 07 May 2025 03:50:32 GMTWed, 07 May 2025 03:50:32 GMT60再次更新一?/title><link>http://www.shnenglu.com/doing5552/archive/2015/03/16/210065.html</link><dc:creator>doing5552</dc:creator><author>doing5552</author><pubDate>Mon, 16 Mar 2015 15:45:00 GMT</pubDate><guid>http://www.shnenglu.com/doing5552/archive/2015/03/16/210065.html</guid><wfw:comment>http://www.shnenglu.com/doing5552/comments/210065.html</wfw:comment><comments>http://www.shnenglu.com/doing5552/archive/2015/03/16/210065.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/doing5552/comments/commentRss/210065.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/doing5552/services/trackbacks/210065.html</trackback:ping><description><![CDATA[q近三十了,再次把这个博客拾h吧?br />距离毕业也已l近五年了,现在也实C一些刚刚开始工作的目标?br />不过Ll的目标q有很远的距,l箋加a吧,完善自己Q?img src ="http://www.shnenglu.com/doing5552/aggbug/210065.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/doing5552/" target="_blank">doing5552</a> 2015-03-16 23:45 <a href="http://www.shnenglu.com/doing5552/archive/2015/03/16/210065.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>联合(union)用法http://www.shnenglu.com/doing5552/archive/2013/01/05/196966.htmldoing5552doing5552Sat, 05 Jan 2013 03:45:00 GMThttp://www.shnenglu.com/doing5552/archive/2013/01/05/196966.htmlhttp://www.shnenglu.com/doing5552/comments/196966.htmlhttp://www.shnenglu.com/doing5552/archive/2013/01/05/196966.html#Feedback1http://www.shnenglu.com/doing5552/comments/commentRss/196966.htmlhttp://www.shnenglu.com/doing5552/services/trackbacks/196966.html联合(union)在C/C++里面见得q不多,但是在一些对内存要求特别严格的地方,联合又是频繁出现Q那么究竟什么是联合、怎么ȝ、有什么需要注意的地方呢?p些问题,我试着做一些简单的回答Q里面肯定还有不当的地方Q欢q指出! 
1、什么是联合Q?/strong>
   “联合”是一U特D的c,也是一U构造类型的数据l构。在一?#8220;联合”内可以定义多U不同的数据cdQ?一个被说明“联合”cd的变量中Q允许装入该“联合”所定义的Q何一U数据,q些数据׃n同一D内存,已达到节省空间的目的Q还有一个节省空间的cdQ位域)?q是一个非常特D的地方Q也是联合的特征。另外,同struct一P联合默认讉K权限也是公有的,q且Q也h成员函数?/div>
2、联合与l构的区别?
   “联合”?#8220;l构”有一些相g处。但两者有本质上的不同。在l构中各成员有各自的内存I间Q?一个结构变量的总长度是各成员长度之和(I结构除外,同时不考虑边界调整Q。而在“联合”中,各成员共享一D内存空_ 一个联合变量的长度{于各成员中最长的长度。应该说明的是, q里所谓的׃n不是指把多个成员同时装入一个联合变量内Q?而是指该联合变量可被赋予M成员|但每ơ只能赋一U| 赋入新值则冲去旧倹{?/div>
   下面举一个例了来加对p合的理解?nbsp;
    ?:
#include <stdio.h>
void main()
{
        union number
        {                   /*定义一个联?/
                int i;
                struct
                {             /*在联合中定义一个结?/
                        char first;
                        char second;
                }half;
        }num;
        num.i=0x4241;         /*联合成员赋?/
        printf("%c%c\n", num.half.first, num.half.second);
        num.half.first='a';   /*联合中结构成员赋?/
        num.half.second='b';
        printf("%x\n", num.i);
        getchar();
}
    输出l果? 
     AB 
     6261 
    从上例结果可以看? 当给i赋值后, 其低八位也就是first和second的? 当给first和second赋字W后, q两个字W的ASCII码也作为i 的低八位和高八位?/div>
3、如何定义?
   例如Q?br style="padding: 0px; margin: 0px;" />    union test
    {
      test() { }
      int office;
      char teacher[5];
    }; 
    定义了一个名为test的联合类型,它含有两个成员,一个ؓ整型Q成员名officeQ另一个ؓ字符数组Q数l名为teacher。联合定义之后,卛_q行联合变量说明Q被说明为testcd的变量,可以存放整型量office或存攑֭W数lteacher?/div>
4、如何说明?
   联合变量的说明有三种形式Q先定义再说明、定义同时说明和直接说明?br style="padding: 0px; margin: 0px;" />   以testcdZQ说明如下:
    1) union test
       {
         int office;
         char teacher[5];
       }; 
       union test a,b;    /*说明a,b为testcd*/
    2) union test
       {
         int office;
         char teacher[5];
       } a,b;
    3) union 
       {
         int office;
         char teacher[5];
       } a,b; 
       l说明后的a,b变量均ؓtestcd。a,b变量的长度应{于test的成员中最长的长度Q即{于teacher数组的长度,?个字节。a,b变量如赋予整型值时Q只使用?个字节,而赋予字W数l时Q可?个字节?/div>
5、如何用?
   对联合变量的赋|使用都只能是对变量的成员q行。联合变量的成员表示为:     
联合变量?成员?nbsp;
例如Qa被说明ؓtestcd的变量之后,可用a.class、a.office 
不允许只用联合变量名作赋值或其它操作Q也不允许对联合变量作初始化赋|赋值只能在E序中进行?br style="padding: 0px; margin: 0px;" />q要再强调说明的是,一个联合变量,每次只能赋予一个成员倹{换句话_一个联合变量的值就是联合变员的某一个成员倹{?/div>
6、匿名联?/strong>
   匿名联合仅仅通知~译器它的成员变量共同n一个地址,而变量本w是直接引用?不用通常的点可符语法.例如Q?br style="padding: 0px; margin: 0px;" />     Qi nclude <iostream>
     void main()
     {
         union{ 
                int test;
                char c; 
               };          
        test=5;
        c=′a′;
        std::cout<<i<<" "<<c;
     }
    正如所见到?联合成分象声明的普通局部变量那栯引用,事实上对于程序而言,q也正是使用q些变量的方?另外,管被定义在一个联合声明中,他们与同一个程序快那的M其他局部变量具有相同的作用域?q意呌匿名联合内的成员的名UC能与同一个作用域内的其他一直标志符冲突.
    对匿名联合还存在如下限制:
    因ؓ匿名联合不用点q算W,所以包含在匿名联合内的元素必须是数?不允许有成员函数Q也不能包含U有或受保护的成员。还?全局匿名联合必须是静?static)的,否则必L在匿名名字空间中?/div>
7、几炚w要讨论的地方Q?/strong>
   1、联合里面那些东西不能存放?
      我们知道Q联合里面的东西׃n内存Q所以静态、引用都不能用,因ؓ他们不可能共享内存?br style="padding: 0px; margin: 0px;" />   2、类可以攑օ联合吗?
      我们先看一个例子:
      class Test
      {
      public:
    Test():data(0) { }
      private:
          int data;
      };
     typedef union _test
     {
Test test;   
     }UI;   
     ~译通不q,Z么呢Q?br style="padding: 0px; margin: 0px;" />     因ؓ联合里不允许存放带有构造函数、析够函数、复制拷贝操作符{的c,因ؓ他们׃n内存Q编译器无法保证q些对象不被破坏Q也无法保证d时调用析够函数?br style="padding: 0px; margin: 0px;" />    3、又是匿名惹的祸Q?
       我们先看下一D代码: 
class test
{
        public:
             test(const char* p);
             test(int in);
             const operator char*() const {return
data.ch;}
             operator long() const {return data.l;}
        private:
     enum type {Int, String };
            union 
     {
const char* ch;
int i;
      }datatype;
      type stype;
      test(test&);
      test& operator=(const test&);
        };
       test::test(const char *p):stype
(String),datatype.ch(p)     { }
       test::test(int in):stype(Int),datatype.l(i)     {
}
     看出什么问题了吗?呵呵Q编译通不q。ؓ什么呢Q难道datatype.ch(p)和datatype.l(i)有问题吗Q?br style="padding: 0px; margin: 0px;" />     哈哈Q问题在哪呢Q让我们来看看构造test对象时发生了什么,当创建test对象Ӟ自然要调用其相应的构造函敎ͼ在构造函C当然要调用其成员的构造函敎ͼ所以其要去调用datatype成员的构造函敎ͼ但是他没有构造函数可调用Q所以出
错?br style="padding: 0px; margin: 0px;" />     注意了,q里可ƈ不是匿名联合Q因为它后面紧跟了个data! 
    4、如何有效的防止讉K出错Q?br style="padding: 0px; margin: 0px;" />       使用联合可以节省内存I间Q但是也有一定的风险Q通过一个不适当的数据成员获取当前对象的|例如上面的ch、i交错讉K?br style="padding: 0px; margin: 0px;" />       Z防止q样的错误,我们必须定义一个额外的对象Q来跟踪当前被存储在联合中的值得cdQ我们称q个额外的对象ؓQunion的判别式?br style="padding: 0px; margin: 0px;" />       一个比较好的经验是Q在处理作ؓcL员的union对象Ӟ为所有union数据cd提供一l访问函数?/div>

doing5552 2013-01-05 11:45 发表评论
]]>POSIX U程http://www.shnenglu.com/doing5552/archive/2012/12/31/196877.htmldoing5552doing5552Mon, 31 Dec 2012 08:06:00 GMThttp://www.shnenglu.com/doing5552/archive/2012/12/31/196877.htmlhttp://www.shnenglu.com/doing5552/comments/196877.htmlhttp://www.shnenglu.com/doing5552/archive/2012/12/31/196877.html#Feedback0http://www.shnenglu.com/doing5552/comments/commentRss/196877.htmlhttp://www.shnenglu.com/doing5552/services/trackbacks/196877.html

POSIX U程详解、POSIX U程~程、NPTL

POSIX 表示可移植操作系l接口(Portable Operating System Interface Q羃写ؓ POSIX 是ؓ了读x?UNIXQ。电气和电子工程师协会(Institute of Electrical and Electronics EngineersQIEEEQ最初开?POSIX 标准Q是Z提高 UNIX 环境下应用程序的可移植性。具体的?POSIX ?IEEE 在各U?UNIX 操作pȝ上运行的软g定义 API 所规定的一pd互相兌的标准的ȝQ?X 则表明其?Unix API 的传ѝLinux 基本上逐步实现?POSIX 兼容Q但q没有参加正式的 POSIX 认证。当前的 POSIX 文档分ؓ三个部分QPOSIX Kernel APIQPOSIX 命o和工具集Q及 POSIX 一致性测试。Posix U程QPOSIX threadsQ又U?PthreadsQ是负责 POSIX ?IEEE 委员会开发的一套线E接口?/p>

Linux U程模型

Linux 最初用的线E模型是 LinuxThread, 它不兼容 POSIXQ而且存在一些性能问题Q所以目?Linux 摒弃了它Q采用了Z Pthreads ?NPTLQNative POSIX Threads Library for LinuxQ模型, NPTL 修复?LinuxThread 的许多缺点,q提供了更好的性能?/p>

回页?/a>



doing5552 2012-12-31 16:06 发表评论
]]>[转]正则表达?0分钟入门教程http://www.shnenglu.com/doing5552/archive/2012/11/09/194962.htmldoing5552doing5552Fri, 09 Nov 2012 02:35:00 GMThttp://www.shnenglu.com/doing5552/archive/2012/11/09/194962.htmlhttp://www.shnenglu.com/doing5552/comments/194962.htmlhttp://www.shnenglu.com/doing5552/archive/2012/11/09/194962.html#Feedback0http://www.shnenglu.com/doing5552/comments/commentRss/194962.htmlhttp://www.shnenglu.com/doing5552/services/trackbacks/194962.html阅读全文

doing5552 2012-11-09 10:35 发表评论
]]>
工作二年http://www.shnenglu.com/doing5552/archive/2012/07/03/181275.htmldoing5552doing5552Tue, 03 Jul 2012 09:58:00 GMThttp://www.shnenglu.com/doing5552/archive/2012/07/03/181275.htmlhttp://www.shnenglu.com/doing5552/comments/181275.htmlhttp://www.shnenglu.com/doing5552/archive/2012/07/03/181275.html#Feedback1http://www.shnenglu.com/doing5552/comments/commentRss/181275.htmlhttp://www.shnenglu.com/doing5552/services/trackbacks/181275.html微博有点他泛滥了

doing5552 2012-07-03 17:58 发表评论
]]>
[ubunt gcc stl] 使用库函?sort() 排序自定义类旉载operator<http://www.shnenglu.com/doing5552/archive/2011/02/15/140098.htmldoing5552doing5552Tue, 15 Feb 2011 09:32:00 GMThttp://www.shnenglu.com/doing5552/archive/2011/02/15/140098.htmlhttp://www.shnenglu.com/doing5552/comments/140098.htmlhttp://www.shnenglu.com/doing5552/archive/2011/02/15/140098.html#Feedback0http://www.shnenglu.com/doing5552/comments/commentRss/140098.htmlhttp://www.shnenglu.com/doing5552/services/trackbacks/140098.htmlclass arc {
……
bool operator<(const arc& b) const;

}

用容器如vector,deque存放arc对象Q再其上使用stl的algrithms中的sort法Q?br>sort(arcVector.begin(),arcVector.end());

Ҏ中需要?#8220;<”作比较操作,故需要重载operator<
单重?bool operator(arc&);
很可能报错:
/usr/include/c++/4.2/bits/stl_algo.h:100: 错误Q?no match ?#8216;operator<’?#8216;__b < __c’
主要是缺const的限定(两个都需要)?br>否则有错Q?br>/usr/include/c++/4.2/bits/stl_algo.h:91: 错误Q??#8216;const arc’作ؓ‘bool arc::operator<(const arc&)’?#8216;this’实参时丢弃了cd限定

分析知道linux中stl下对CQ+的类型安全约束很强,const保证导入对象和自w对象都不能被修攏V?br>而stl的sort操作实不需要修Ҏ较的对象Q也不应该被修改Q故强制使用的自定义operator<需要两个const限制比较的两个对象?br>
使用friendҎQ?br>friend bool operator<(const arc&, const arc&);

两种错误Q?br>1.friend bool operator<(const arc&, const arc&) const;
错误Q?non-成员函数‘bool operator<(const arc&, const arc&)’不能拥有 cv 限定W?br>
2.bool operator<(const arc&, const arc&) [const]
错误Q?‘bool arc::operator<(const arc&, const arc&) const’带且仅带 1 个实?

doing5552 2011-02-15 17:32 发表评论
]]>
linux Grep 用法http://www.shnenglu.com/doing5552/archive/2010/11/01/132025.htmldoing5552doing5552Mon, 01 Nov 2010 11:08:00 GMThttp://www.shnenglu.com/doing5552/archive/2010/11/01/132025.htmlhttp://www.shnenglu.com/doing5552/comments/132025.htmlhttp://www.shnenglu.com/doing5552/archive/2010/11/01/132025.html#Feedback0http://www.shnenglu.com/doing5552/comments/commentRss/132025.htmlhttp://www.shnenglu.com/doing5552/services/trackbacks/132025.htmlc2008-04-02 09:12
Grep : g (globally) search for a re (regular expression ) and p (print ) the results.

1、参敎ͼ
-I Q忽略大写
-c Q打印匹配的行数
-l Q从多个文g中查扑֌含匹配项
-v Q查找不包含匚w的?
-nQ打印包含匹配项的行和行?

2、REQ正则表辑ּQ?
\ 忽略正则表达式中Ҏ字符的原有含?
^ 匚w正则表达式的开始行
$ 匚w正则表达式的l束?
\< 从匹配正则表辑ּ的行开?
\>; 到匹配正则表辑ּ的行l束
[ ] 单个字符Q如[A] 即AW合要求
[ - ] 范围 Q如[A-Z]即AQBQC一直到Z都符合要?
. 所有的单个字符
* 所有字W,长度可以?

3、D?
# ps -ef | grep in.telnetd
root 19955 181 0 13:43:53 ? 0:00 in.telnetd

# more size.txt size文g的内?
b124230
b034325
a081016
m7187998
m7282064
a022021
a061048
m9324822
b103303
a013386
b044525
m8987131
B081016
M45678
B103303
BADc2345

# more size.txt | grep '[a-b]' 范围 Q如[A-Z]即AQBQC一直到Z都符合要?
b124230
b034325
a081016
a022021
a061048
b103303
a013386
b044525
# more size.txt | grep '[a-b]'*
b124230
b034325
a081016
m7187998
m7282064
a022021
a061048
m9324822
b103303
a013386
b044525
m8987131
B081016
M45678
B103303
BADc2345

# more size.txt | grep '' 单个字符Q如[A] 即AW合要求
b124230
b034325
b103303
b044525
# more size.txt | grep '[bB]'
b124230
b034325
b103303
b044525
B081016
B103303
BADc2345

# grep 'root' /etc/group
root::0:root
bin::2:root,bin,daemon
sys::3:root,bin,sys,adm
adm::4:root,adm,daemon
uucp::5:root,uucp
mail::6:root
tty::7:root,tty,adm
lp::8:root,lp,adm
nuucp::9:root,nuucp
daemon::12:root,daemon

# grep '^root' /etc/group 匚w正则表达式的开始行
root::0:root


# grep 'uucp' /etc/group
uucp::5:root,uucp
nuucp::9:root,nuucp

# grep '\<uucp' /etc/group
uucp::5:root,uucp


# grep 'root$' /etc/group 匚w正则表达式的l束?
root::0:root
mail::6:root


# more size.txt | grep -i 'b1..*3' -i Q忽略大写

b124230
b103303
B103303

# more size.txt | grep -iv 'b1..*3' -v Q查找不包含匚w的?

b034325
a081016
m7187998
m7282064
a022021
a061048
m9324822
a013386
b044525
m8987131
B081016
M45678
BADc2345

# more size.txt | grep -in 'b1..*3'
1:b124230
9:b103303
15:B103303

# grep '$' /etc/init.d/nfs.server | wc -l
128
# grep '\$' /etc/init.d/nfs.server | wc –l 忽略正则表达式中Ҏ字符的原有含?

15
# grep '\$' /etc/init.d/nfs.server
case "$1" in
>;/tmp/sharetab.$$
[ "x$fstype" != xnfs ] && \
echo "$path\t$res\t$fstype\t$opts\t$desc" \
>;>;/tmp/sharetab.$$
/usr/bin/touch -r /etc/dfs/sharetab /tmp/sharetab.$$
/usr/bin/mv -f /tmp/sharetab.$$ /etc/dfs/sharetab
if [ -f /etc/dfs/dfstab ] && /usr/bin/egrep -v '^[ ]*(#|$)' \
if [ $startnfsd -eq 0 -a -f /etc/rmmount.conf ] && \
if [ $startnfsd -ne 0 ]; then
elif [ ! -n "$_INIT_RUN_LEVEL" ]; then
while [ $wtime -gt 0 ]; do
wtime=`expr $wtime - 1`
if [ $wtime -eq 0 ]; then
echo "Usage: $0 { start | stop }"


# more size.txt

the test file
their are files
The end

# grep 'the' size.txt
the test file
their are files

# grep '\<the' size.txt
the test file
their are files

# grep 'the\>;' size.txt
the test file

# grep '\<the\>;' size.txt
the test file

# grep '\<[Tt]he\>;' size.txt
the test file
The end



doing5552 2010-11-01 19:08 发表评论
]]>HTTP代理如何正确处理Cookiehttp://www.shnenglu.com/doing5552/archive/2010/10/10/129374.htmldoing5552doing5552Sun, 10 Oct 2010 14:29:00 GMThttp://www.shnenglu.com/doing5552/archive/2010/10/10/129374.htmlhttp://www.shnenglu.com/doing5552/comments/129374.htmlhttp://www.shnenglu.com/doing5552/archive/2010/10/10/129374.html#Feedback0http://www.shnenglu.com/doing5552/comments/commentRss/129374.htmlhttp://www.shnenglu.com/doing5552/services/trackbacks/129374.html2005 q?11 ?10 ?/p>
大多数的 Web 应用E序都要求维护某U会话状态,如用戯物R的内宏V这U会话状态的保持很多情况下需要借助于Cookie或者Session的帮助。本文结合在UK面翻?QMachine Translation SystemQ项目中对于Cookie的处理方法,探讨一下如何在HTTP应用代理中正处理Cookie的传递和理问题?/blockquote>

读者定位ؓhJava和Web开发经验的开发和设计人员?/p>

读者可以学习到关于Cookie的工作原理和Cookie协议的细节,以及在一个HTTP应用代理的场景下Cookie的管理和处理思想Qƈ可以直接使用文中的代码和思\Q提高工作效率?/p>

随着来多的系l移植到了Web上,HTTP协议h了比以前更广泛的应用。不同的pȝ对WEB实现提出了不同的要求Q基于HTTP协议的网l应用正于复杂化和多元化。很多应用需要把用户h的页面进行处理后再返回给用户Q比如页面关键字qoQ页面内容缓存、内Ҏ索、页面翻译等{。这些应用在实际效果上类g一个HTTP应用代理Q它们首先接受用LhQ根据用戯求的URLȝ正的目标服务器取回目标页面,再根据不同应用的要求做出相应处理后返回给用户。这LL接面对的是q个HTTP应用代理Q而通过它与其他面q行交互。Cookie或Session技术的应用Q解决了HTTP协议的一个问?-- 无法保持客户状态,因此它现在被q泛应用于各UWeb站点中。上面提到的那些应用如果不能处理好Cookie和Session的传递、更新和废除{问题,׃极大的限制它们所能处理站点的范围Q因此如何在HTTP应用代理中正处理CookieQ成Z个必解决的问题。本文结合在面译QMachine Translation SystemQ项目中对于Cookie的处理方法,探讨一下这斚w的解x案?/p>

MTS目介及讨论前提

Machine Translation SystemQ以下简UMTSQ是一个在U实旉面翻译系l,为用户在U提供把英文面译成其?U语a的服务。用户通过向MTSpȝ提交一个类g面的URL使用此服务,其中参数url指明了用h需要翻译的目标地址Q参数language指明了所需译成的目标语言Qwww.mts.com是假想中提供MTS服务的站炏V?/p>

HTTP://www.mts.com/translate?url=http://www.ibm.com/&language=French

一个完整的MTSpȝ处理q程可以分解成以下几个步骤:

  • 用户向MTS提交合适的URL?
  • MTS在接到用Lh后,解析出用户需要翻译的目标地址和目标语aQ根据用戯求的目标地址Q把h转发到目标服务器?
  • MTS接受来自目标服务器的应答Q包括页面信息和HTTP头信息?
  • MTS在确定得到正的目标面后,把页面内定w入WebSphere Translation Serverq行译?
  • 把翻译后的页面连同修改后的HTTP头信息提交给用户?

MTS逻辑?/strong>
MTS逻辑?src="http://www.ibm.com/developerworks/cn/java/j-cookie/images/image002.jpg"

当然Q这其中涉及到很多的应用处理。比如与各种HTTP/HTTPS站点建立联结、根据HTTP头信息进行页面蟩转和错误处理、ؓ始终保持用户在翻译模式下而对目标的HTML面q行分析和修改,Ҏpȝ讄Ҏ些DNTQDo Not TranslateQ的面q行qo和蟩转,当然q有对Cookie的处理等{。其他问题跟q篇文章兌不大Q我们重点讨论在q种情况下的Cookie处理。Cookie跟随目标服务器的HTTP头信息被MTS接收刎ͼl过MTS整理之后发给客户端浏览器。MTS在接C一ơ用户对同一个站点的译hӞ再把从客L得到的Cookie发送给目标服务器?/p>

在以上的场景中,MTS充当的作用类g一UHTTP应用代理服务器,它代替用户取得目标页面,q在作出相应处理后再提交l用戗当Ӟq种代理服务器不需要用户修Ҏ览器的代理服务器参数或者网l配|,而只是简单的在浏览器的地址栏中输入一个MTS能够识别的URL卛_。此文章也是在q样一个应用场景的基础上,展开对HTTP应用代理服务器如何处理Cookie的讨论?/p>



回页?/font>


问题的?/span>

在MTSpȝ中,目标服务器的Cookie在两个地方会产生问题。当MTS接收目标服务器应{的时候,Cookie随着HTTP头信息被MTS接收到的。这时候目标服务器认ؓMTS是最l客P因此它赋予了Cookie与目标服务器相符的属性。而如果MTS把这些Cookie原封不动的保存在HTTP头信息中Q传l真正的最l用L话,用户的浏览器会因些Cookie不合法而忽略它们。同理,当Cookie从浏览器端传回目标服务器的时候,也会遇到相同的问题。因此有必要对Cookieq行一些处理,以保证用L览器能真正识别和利用这些Cookie?/p>

但是Z用户览器无法识别从目标服务器传q来的原始Cookie呢?q是因ؓZ安全性的考虑QCookie规范制定的时候对Cookie的生和接受讄了一些严格的规范Q不W合q些规范的CookieQ浏览器和服务器都将予以忽略。下面我们从Cookie规范入手q行介绍?/p>



回页?/font>


Cookie的规范介l?/span>

目前有以下几UCookie规范Q?/p>

  • Netscape cookie草案Q是最早的cookie规范Q基于rfc2109。尽这个规范与rc2109有较大的差别Q但是很多服务器都与之兼宏V?
  • rfc2109Q?是w3c发布的第一个官方cookie规范。理ZԌ所有的服务器在处理cookie(版本1)Ӟ都要遵@此规范。遗憄是,q个规范太严gQ以致很多服务器不正的实施了该规范或仍在用Netscape规范?
  • rfc2965规范定义了cookie版本2Qƈ说明了cookie版本1的不?

rfc2965规范的用,目前q不多。rfc2109规范相应要严格得多,在实际应用上Qƈ不是所有的览器和Web服务器都严格遵守。因此相比较而言QNetscape cookie草案倒是一个比较简z和被广泛支持的Cookie规范Q因此我们在q里以Netscape cookie草案为基q行讨论Q对于其他两U规范,我们的讨论和代码h相同的意义。关于Netscape cookie草案的细节,大家可以参照Netscape官方站点Q这里我们列举一些和我们讨论有关的内宏V?/p>

ҎNetscape cookie草案的描qͼCookie 是Web 服务器向用户的浏览器发送的一DASCII码文本。一旦收到CookieQ浏览器会把Cookie的信息片断以"???name-value pairs)的Ş式储存保存在本地。这以后Q每当向同一个Web 服务器请求一个新的文档时QWeb 览器都会发送之站点以前存储在本地的Cookie。创建Cookie的最初目的是惌Web服务器能够通过多个HTTPhq踪客户。有些复杂的|络应用需要在不同的网之间保持一_它们需要这U会话状态的保持能力?/p>

览器与Web服务器通过HTTP协议q行通讯Q而Cookie是保存在HTTP协议的请求或者应{头部(在HTTP协议中,数据包括两部分,一部分是头部,׃些名值对构成Q用来描q要被传输数据的一些信息。一部分是主?body)Q是真正的数据(如HTML面{)Q进行传送的?/p>

在HTML文档被发送之前,Web服务器通过传送HTTP 包头中的Set-Cookie 消息把一个cookie 发送到用户的浏览器中。下面是一个遵循Netscape cookie草案的完整的Set-Cookie _


Set-CookieQcustomer=huangxp; path=/foo; domain=.ibm.com;
            expires= Wednesday, 19-OCT-05 23:12:40 GMT; [secure]
            

Set-Cookie的每个属性解释如下:

  • Customer=huangxp 一?名称Q?对,把名Ucustomer讄为?huangxp"Q这个属性在Cookie中必L?
  • path=/foo 控制哪些讉K能够触发cookie 的发送。如果没有指定pathQcookie 会在所有对此站点的HTTP 传送时发送。如果path=/directoryQ只有访?directory 下面的网|Qcookie才被发送。在q个例子中,用户在访问目?foo下的内容Ӟ览器将发送此cookie。如果指定了pathQ但是path与当前访问的url不符Q则此cookie被忽略?
  • domain=.ibm.com 指定cookie被发送到哪台计算Z。正常情况下Qcookie只被送回最初向用户发送cookie 的计机。在q个例子中,cookie 会被发送到M?ibm.com域中的主机。如果domain 被设为空Qdomain p讄为和提供cookie 的Web 服务器相同。如果domain不ؓI,q且它的值又和提供cookie的Web服务器域名不W,q个Cookie被忽略?
  • expires= Wednesday, 19-OCT-05 23:12:40 GMT 指定cookie 失效的时间。如果没有指定失效时_q个cookie ׃会被写入计算机的盘上,q且只持l到q次会话l束?
  • secure 如果secure q个词被作ؓSet-Cookie 头的一部分Q那么cookie 只能通过安全通道传输Q目前即SSL通道Q。否则,览器将忽略此Cookie?

一旦浏览器接收了cookieQ这个cookie和对q端Web服务器的q箋h一赯览器发送。例?前一个cookie 被存入浏览器q且览器试图请?URL http://www.ibm.com/foo/index.html Ӟ下面的HTTP 包头p发送到q端的Web服务器?/p>

GET /foo/index.html HTTP/1.0
CookieQcustomer=huangxp





回页?/font>


一ơ典型的|络览q程

在了解了Cookie协议的一些基本内容之后,让我们看看一ơ典型的|络览q程中浏览器如何识别和处理CookieQ?/p>

  • 览器对于Web服务器应{包头中Cookie的操作步骤:
    1. 从Web服务器的应答包头中提取所有的cookie?br>2. 解析q些cookie的组成部分(名称Q|路径{等Q?br>3. 判定L是否允许讄q些cookie。允许的话,则把q些Cookie存储在本地?
  • 览器对Web服务器请求包头中所有的Cookieq行{选的步骤Q?br>1. Ҏh的URL和本地存储cookie的属性,判断那些Cookie能被发送给Web服务器?br>2. 对于多个cookieQ判定发送的序?br>3. 把需要发送的Cookie加入到请求HTTP包头中一起发送?




回页?/font>


由MTS代理的网l浏览过E?/span>

以上我们了解了在一个典型的览器与Web服务器交互的时候,Cookie的传递过E。下面我们将看到Q如果在MTS代理|络览的过E中Q不对Cookieq行修改Q上面的Cookie传递过E将无法实现?/p>

1. 假设用户希望?http://www.ibm.com/foo/index.html 面译成法文,应该使用如下的url对MTS发出h

Q?

http://www.mts.com/translate?url=http://www.ibm.com/foo/index.html&language=French

2. MTS接收用户的请求,q接q程目标服务?http://www.ibm.com/foo/index.html。目标服务器做出应答Q返回HTTP头和HTML面内容。其中,典型的HTTP头内容如下:


HTTP/1.1 200 OK
            Date: Mon, 24 Oct 2005 06:54:41 GMT
            Server: IBM_HTTP_Server
            Cache-Control: no-cache
            Content-Length: 19885
            Connection: close
            Set-CookieQcustomer=huangxp; path=/foo; domain=.ibm.com;
            expires= Wednesday, 19-OCT-05 23:12:40 GMT
            Content-Type: text/html
            

3. MTS不对Set-Cookie后的内容作Q何处理,直接把它加到用户览器的应答头上发送给览器?/p>

4. 览器将从Set-Cookie中解析出domain和path的|分别?ibm.com?fooQƈ与请求的urlQhttp://www.mts.com/translate?url=http://www.ibm.com/foo/index.html&language=Frenchq行比较。请求url的domain是www.mts.comQpath?Q与Set-Cookie中的属性不W,所以浏览器忽略此Cookie?/p>

另外Q在览器发送Cookie的时候也会遇到同L问题Q同样如上例Q如果浏览器里本来已l存储了http://www.ibm.com/foo/的CookieQ但׃用户要通过MTS讉K此站点,览器经不会把已l存储的Cookie上{到MTS中,MTS也就无法把之传递到http://ibm.com/foo/上?/p>

Z上面Cookie规范的介l和例证Q我们能看出Q浏览器在接受某一个站点的Cookie的时候,需要检查Cookie的参数domain、path、secureQ看是否与当前的站点和URL相符Q如果不W的话,׃忽略。另一斚w。浏览器在上传Cookie的时候,也会Ҏ当前所讉K站点的属性,上传相关的CookieQ而其他的Cookie则不予上传?/p>

xQ我们讨Z需要修改Cookie的根本原因在于Cookie规范的限制。下面我们讨ZU解决问题的思\?/p>



回页?/font>


解决问题的两U思\

Cookie的存在是要解决HTTP协议本n先天的缺?无状态性,它ؓ用户保存了一些需要的状态信息。因此我们解x问题的最本质的出发点Q也是扑ֈ一U途径能ؓ用户保存Cookie所提供用户状态信息,实际上就是Name/Value寏V?/p>

思\一

W一U思\是修改目标服务器取得的CookieQ之符合MTS站点的属性,然后作ؓMTS站点的Cookie存储到用L览器中厅R当Ӟq种修改必须保留原始Cookie的所有属性|当以后访问同一个目标服务器的时候,MTS能根据保存的属性D原出原始CookieQ然后进行提交?/p>

具体到属性值的保存位置Q没有太多选择的余圎ͼ实际上,domainQpathQsecureQexpiresq几个属性都无法利用Q只有利用name=valueq一属性对。我们的做法是创造一个新的CookieQ把原始Cookie的domainQpath的gnameD行编码,用分隔符附加在Name值的后面Q符值给新的Cookie。这样做也同旉免了不同目标服务器如果出现同名的CookieQ将会互相覆盖的情况QCookie规范里面也规定了Q客L以domainQpathQname作ؓCookie的唯一标示Q。而原始Cookie的secure和expires|直接W给新的CookieQ新Cookie的domain和path设成~省|q样Q新Cookie可以被览器正常接受。由于浏览器接受的所有Cookie的domain和path值都一P因此每次用户对MTS提出hӞ览器都会把所有与MTS站点相关的Cookie上传Q因此,MTSq需要还原原始的CookieQ过滤掉与目标服务器不相q的CookieQ然后上传有用的Cookie?/p>

q种思\的优点在于Cookie存储在客LQ可以做到长期存储,览器自己根据Cookie的expires值做出判断,省掉很多开发的ȝ。缺Ҏ转换的过E相对较复杂。另外还有一个缺点,也是׃Cookie规范的限制所造成的。Cookie规范对于一个浏览器同时能够存储的Cookie数量作出了规定?/p>

  • d300 个cookie
  • 每个Cookie 4 K 的存储容?
  • 每一个domain 或?server 20 个cookie?

以上是浏览器所应达到的最存储数量,出q个限制Q浏览器应该自动按照最最q被使用的原则删除超出得Cookie。由于用h可能通过MTSq一个网站翻译大量的目标服务器,因此览器存储在MTS的domain下的cookie数量很有可能超q?0个,q时候就会导致某些Cookie被删除。一般这也不会造成太大问题Q因范是要求览器删除最最q被使用的CookieQ但我们在实际测试当中发现有些浏览器q不遵守q样的规范,而是删除最新的CookieQ这将D用户很大的不ѝ?/p>

思\?/font>

W二U思\在于把原始的Cookiel织成dataBeanQ存储到用户的Session当中厅R这P在用L只需要存储一个SessionID的CookieQ而不需要存储所有目标服务器的每一个Cookie。另外,当接收到用户的又一ơ翻译请求时Q再从Session当中取出所有的dataBeanQ逐一q行分析Q找Z用户所h的目标服务器相符的原始CookieQ进行提交?/p>

q种思\可以克服上一U思\中Cookie过标准数量时的~陷Q而且不需~码保存原始的Cookie属性|减少了程序的复杂度。缺Ҏ需要程序员自己处理expires。而且׃是把Cookie存储在Session中,一旦Session失效Q所有Cookie都将被删除,所以,无法保存那些长期的Cookie?/p>

MQ两U思\各有利弊Q在实际应用当中要权衡考虑。下面我们针对两U思\q行技术实玎ͼ分别对应Ҏ一和方案二?/p>

׃MTS需要与目标服务器连接,遵@HTTP协议d和返回CookieQ但是如果用JDK中的java.net.URLConnection处理Cookie非怸方便Q因此我们用HTTPClient来处理与目标服务器的q接?/p>



回页?/font>


Ҏ一QCookie存储在浏览器?/span>

用户每发起一ơ新的请求,览器在查完本地存储Cookie的有效性后Q会把所有由MTS产生的有效Cookie附加在请求头里送到MTS。MTS接受到客L的翻译请求后Q从Request中提取出所有的CookieQ还原后Ҏ目标服务器的domain和pathq行qo。生所有与目标服务器相关的Cookie?/p>
//从request中获取所有的Cookie
            javax.servlet.http.Cookie[] theCookies = request.getCookies();
            ArrayList cookiesList = new ArrayList();
            String url = request.getParameter("url");
            String domain = URLUtil.getURLHost(url);
            String path = URLUtil.getPath(url);
            if (theCookies != null)
            {
            for (int i = 0; i < theCookies.length; i++)
            {
            RE r = new RE();
            //用正则表辑ּ把name还原成domainQpathQname
            REDebugCompiler compiler = new REDebugCompiler();
            r.setProgram(compiler.compile("\\|\\|"));
            String[] values = r.split(theCookies[i].getName());
            //"9.181.116.183||/MTModule||testCookie:value1" or " ||
            ||testCookie:value1"
            if (values.length == 3)
            {
            if (values[0].trim().startsWith("."))
            {
            if (!domain.endsWith(values[0].trim()))
            continue;
            } else if (!domain.endsWith("://" + values[0].trim()))
            continue;
            if (!path.startsWith(values[1].trim()))
            continue;
            Cookie tempCookie = new Cookie();
            tempCookie.setDomain(
            ("".equals(values[0].trim())) ? null : values[0]);
            tempCookie.setPath(
            ("".equals(values[1].trim())) ? null : values[1]);
            tempCookie.setName(
            ("".equals(values[2].trim())) ? null : values[2]);
            tempCookie.setSecure(theCookies[i].getSecure());
            tempCookie.setValue(theCookies[i].getValue());
            tempCookie.setVersion(theCookies[i].getVersion());
            tempCookie.setComment(theCookies[i].getComment());
            cookiesList.add(tempCookie);
            }
            }
            }
            //transferedCookie用来存储被传到目标服务器的Cookie
            Cookie[] transferedCookie = new Cookie[cookiesList.size()];
            cookiesList.toArray(transferedCookie);
            

接下来,需要把Cookie送到目标服务器中。我们用HTTPClient与目标服务器q接。HTTPClient在与目标服务器连接以后,允许服务器设|Cookieq在需要的时候自动将Cookieq回服务器,也支持手工设|?Cookie后发送到服务器端。但是,׃如何处理cookie有几个规范互相冲H:Netscape Cookie 草案、RFC2109、RFC2965Q而且q有很大数量的Y件商的Cookie实现不遵循Q何规范?Z处理q种状况Q需要把HttpClient讄成Cookie兼容模式Q这样可以最大限度的处理好各UCookie。下面的代码把Cookie送到目标服务器?/p>
HttpClient client = new HttpClient();
            //从request得到所有需要传输的cookie
            Cookie[] questCookie = getCookieFromRequest(request);
            //讄HTTPClient为Cookie兼容模式
            client.getState().setCookiePolicy(CookiePolicy.COMPATIBILITY);
            if (questCookie.length > 0)
            //把Cookie加到httpclient?
            client.getState().addCookies(questCookie);
            HttpMethod method = new GetMethod(TagerURL);
            //向目标服务器发送请?
            int statusCode = client.executeMethod(method);
            method.releaseConnection();
            

MTS把请求和Cookie送出后,l箋接收目标服务器的应答Q读取返回的原始CookieQƈ转换成可以存储在用户览器端的Cookie。下面的代码对原始Cookie的内容进行变换,保留expires和secure{项Q把domain和path编码到name中去?/p>
//从HTTPClient中取得所有的Cookie
            Cookie[] temp = client.getState().getCookies();
            if (temp != null)
            {
            javax.servlet.httpCookie theCookie = new javax.servlet.http.Cookie[temp.length];
            //逐一对Cookieq行处理
            for (int i = 0; i < temp.length; i++)
            {    StringBuffer sb = new StringBuffer();
            //~码成domain||path||name
            sb.append(
            temp[i].getDomain() == null ? " " : temp[i].getDomain());
            sb.append("||");
            sb.append(temp[i].getPath() == null ? " " : temp[i].getPath());
            sb.append("||");
            sb.append(temp[i].getName() == null ? " " : temp[i].getName());
            theCookie[i] =
            new Cookie(sb.toString(),temp[i].getValue());
            //复制其他?
            theCookie[i].setMaxAge(theCookie[i].getMaxAge();
            theCookie[i].setSecure(temp[i].getSecure());
            theCookie[i].setVersion(temp[i].getVersion());
            theCookie[i].setComment(temp[i].getComment());
            }
            }
            

最后一步,把这些Cookie保存到response里,随HTTP应答头返回用h览器。ƈ保存在浏览器中?/p>
//把所有{换后的Cookie加入response
            for (int i = 0; i < theCookie.length; i++) {
            response.addCookie(theCookie[i]);
            }
            

xQ我们已l完成了接收用户hQ{换CookieQ发送到目标服务器,接收目标服务器的原始CookieQƈ保存在客h览器的整个处理过E?/p>



回页?/font>


Ҏ二:Cookie存储在服务器?/span>

在此U方案中Q目标服务器q回lMTS的Cookie被l织成dataBeanQ存储在用户的Session中。因此,我们首先生成一个用来存储Cookie的类CookiesBeanQ根据它的特性,它可以承ArraryListcR此对象存储用戯问目标服务器时接收到的所有CookieQƈ提供与新接收到的Cookie融合的功能,同时能够删除q期的CookieQ更新同名的Cookie?/p>
public class CookiesBean extends ArrayList
            {
            /**
            * 处理Cookies.
            * @参数 Cookies array
            */
            public CookiesBean(Cookie[] cook)
            {
            if (cook == null)
            return;
            //add all cookie which isn't expired.
            for (int i = 0; i < cook.length; i++)
            {
            if (!cook[i].isExpired())
            {
            add(cook[i]);
            }
            }
            }
            /**
            * 融合参数中的bean
            * @参数 bean
            * 参? rfc2109 4.3.3  Cookie Management
            */
            public void RefreshBean(CookiesBean bean)
            {
            if (bean == null)
            return;
            Iterator it = bean.iterator();
            //针对bean中的每一个Cookieq行处理
            while (it.hasNext())
            {
            Cookie beanCookie = (Cookie) it.next();
            if (beanCookie == null) continue;
            ArrayList drop = new ArrayList();
            Iterator thisIt = iterator();
            //取出存储的Cookieq行比较和处?
            while (thisIt.hasNext())
            {
            Cookie thisCookie = (Cookie) thisIt.next();
            if (thisCookie == null) continue;
            //比较nameQdomain和path,如果一L话,则把此CookieUddrop?
            if (CommonMethods
            .CompString(beanCookie.getName(), thisCookie.getName())
            					&& CommonMethods.CompString(
            beanCookie.getDomain(),
            thisCookie.getDomain())
            && CommonMethods.CompString(
            beanCookie.getPath(),
            thisCookie.getPath()))
            {
            drop.add(thisCookie);
            continue;
            }
            //删除q期的Cookie
            if (thisCookie.isExpired())
            drop.add(thisCookie);
            }
            //删除所有drop中的Cookie
            this.removeAll(drop);
            //如果beanCookie有效Q则加入到存储区中?
            if (!beanCookie.isExpired())
            add(beanCookie);
            }
            return;
            }
            }
            

当MTS接受到客L的翻译请求后Q会从Session中提取出所有的dataBeanQƈ得到存储的所有Cookie。如以下代码Q?/p>
				CookiesBean dataBean = null;
            Cookie[] theCookies = new Cookie[0];
            ArrayList cookiesList = new ArrayList();
            //获得SessionQƈ获得dataBean
            HttpSession session = request.getSession(false);
            if (session != null)
            {
            dataBean = (CookiesBean) session.getAttribute(SESSION_NAME);
            }
            else
            {
            return theCookies;
            }
            

MTS在所有的存储的Cookie中,查Cookie的Domain、path和secure的|{选出W合目标服务器的Cookie?/p>
				//提取目标服务器的domain和path
            String url = context.getURL();
            String domain = URLUtil.getURLHost(url);
            String path = url.substring(domain.length());
            String cookiedomain = null;
            String cookiepath = null;
            //逐个比较Cookie的domain和path
            //把符合要求的CookieU录到cookiesList?
            for (int i = 0; i < dataBean.size(); i++)
            {
            Cookie cookie = (Cookie) dataBean.get(i);
            if (cookie == null) continue;
            cookiedomain =
            (cookie.getDomain() == null) ? "" : cookie.getDomain();
            cookiepath = (cookie.getPath() == null) ? "  " : cookie.getPath();
            if (!path.startsWith(cookiepath))
            continue;
            if (cookiedomain.startsWith("."))
            {
            if (!domain.endsWith(cookiedomain))
            continue;
            }
            else if (!domain.endsWith("://" + cookiedomain))
            continue;
            if (cookie.isExpired())
            continue;
            if (cookie.getSecure() && url.toLowerCase().startsWith("http:"))
            continue;
            cookiesList.add(cookie);
            }
            theCookies = new Cookie[cookiesList.size()];
            cookiesList.toArray(theCookies);
            return theCookies;
            

把Cookie送到目标服务器的代码与方案一基本一P在此忽略?/p>

最后一步,需要把Cookie存储到Session中。下面的代码从目标服务器接受CookieQ融入到dataBean中,q保存到客户的Session中?/p>
		//从目标服务器得到Cookie?
            Cookie[] cookies = client.getState().getCookies();
            CookiesBean bean = new CookiesBean(cookies);
            CookiesBean dataBean = bean;
            //取得用户Session
            HttpSession session =  request.getSession(false);
            if (session != null)
            {
            if (session.getAttribute(SESSION_NAME) != null)
            {
            //dSession中存取的dataBean
            dataBean = (CookiesBean) session.getAttribute(SESSION_NAME);
            //目标服务器端的Cookie融合到Session中的dataBean?
            dataBean.RefreshBean(bean);
            }
            //把最l的dataBean存入Session?
            session.setAttribute(SESSION_NAME, dataBean);
            }
            

xQ我们已l完成了在Session中保存个目标服务器所产生Cookie的整个处理过E?/p>



回页?/font>


关于Session的考虑

在研I完如何理和传递Cookie之后Q我们也需要研I一下Session的传递。因为目前大部分站点都在采用Session机制保存用户状态数据,如果不能解决Session的传递问题,HTTP应用代理服务器的适用范围同样会大打折扣?/p>

首先我们了解一下Session的实现机制。Session是一U服务器端的机制Q服务器使用一U类g散列表的l构来保存信息。当E序需要ؓ某个客户端的h创徏一个session的时候,服务器首先检查这个客L的请求里是否已包含了一个session标识 - UCؓsession idQ如果已包含一个session id则说明以前已lؓ此客L创徏qsessionQ服务器按照session id把这个session索出来用(如果索不刎ͼ可能会新Z个)Qsession id的值应该是一个既不会重复Q又不容易被扑ֈ规律以仿造的字符丌Ӏ?/p>

保存q个session id的方式之一是采用Cookie。一般这个Cookie的名字都cM?SESSIONID。比如WebSphere对于Web应用E序生成的CookieQJSESSIONID= 0001HWF4iVD94pY8Cpbx6U4CXkf:10lro0398Q它的名字就?JSESSIONID?/p>

保存session id的其他方式还包括URL重写和表单隐藏字Dc这两种方式都不需要代理服务器作特D处理。因此实际上Q我们解决了Cookie的管理和传递的问题之后Q也p决了Session的管理和传递?/p>



回页?/font>


l束?/span>

从上面的讨论中可以看出,׃Cookie本n的规范限ӞHTTP应用代理所必需面对的一个问题就是如何对Cookieq行正确的处理。本文对此提Z两种解决思\q列Z实现代码。对于MTS目本nQ我们用的是第二种Ҏ。开发h员在认识好Cookie本n的特性之后,参照本文的思\Q根据自ql的特点Q也会找出更适宜的解x案?/p>

参考资?

  • Netscape Cookie Specification 对Netscape Cookie 使用的特性进行了要的介绍?br>
  • RFC2965QHTTP State Management Mechanism 介绍了HTTP 状态管理机?br>
  • RFC2109 w3c发布的第一个官方cookie规范

  • RFC2616QHypertext Transfer Protocol 文本传输协?br>
  • Ronald Tschalr开发了 HTTPClientQ将其作?URLConnection 的替代品?br>
  • Jakarta Regexp Apache 的开源项目,处理正则表达式的java包?br>


关于作?/span>

 

黄湘qx一名工作在IBM CSDL的高UY件工E师Q从1997q开始从事网l开发设计工作。他对Java的网l和Web开发有丰富的经验,对底层协议也有一定的了解。现在正从事于页面在U翻译项目的开发和支持。你可以通过jobike@sina.com与黄湘^联系?/p>



doing5552 2010-10-10 22:29 发表评论
]]>(?指针的引用(*&Q与指针的指针(**Q?/title><link>http://www.shnenglu.com/doing5552/archive/2010/09/28/127994.html</link><dc:creator>doing5552</dc:creator><author>doing5552</author><pubDate>Tue, 28 Sep 2010 14:06:00 GMT</pubDate><guid>http://www.shnenglu.com/doing5552/archive/2010/09/28/127994.html</guid><wfw:comment>http://www.shnenglu.com/doing5552/comments/127994.html</wfw:comment><comments>http://www.shnenglu.com/doing5552/archive/2010/09/28/127994.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/doing5552/comments/commentRss/127994.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/doing5552/services/trackbacks/127994.html</trackback:ping><description><![CDATA[在下列函数声明中Qؓ什么要<a class=vLink1 id=vad_8 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,8,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,8)" target=_blank name=8>同时</a>使用*?amp;W号Q以及什么场合用这U声明方? <br>  void func1Q?MYCLASS *&pBuildingElement Q; <br><br>  论坛中经常有人问到这L问题。本文试?a class=vLink1 id=vad_4 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,4,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,4)" target=_blank name=4>通过</a>一?a class=vLink1 id=vad_9 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,9,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,9)" target=_blank name=9>实际</a>的指针?a class=vLink1 id=vad_7 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,7,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,7)" target=_blank name=7>l验</a>来解释这个问题?br>仔细看一下这U声明方式,实有点让hqh。在某种意义上,"*"?&"是意思相对的两个东西Q把它们攑֜一h什么意义呢Q。ؓ了理解指针的q种做法Q我们先复习一下C/C++~程中无所不在的指针概c我们都知道MYCLASS*的意思:指向某个对象的指针,此对象的cd为MYCLASS?Void func1QMYCLASS *pMyClassQ; <br><br>// 例如Q?MYCLASS* p = new MYCLASSQ?br>func1QpQ; <br>上面q段代码的这U处理方法想必谁都用q,创徏一个MYCLASS对象Q然后将它传入func1函数。现在假设此函数要修改pMyClassQ?void func1QMYCLASS *pMyClassQ?br>{<br>DoSomethingQpMyClassQ;<br>pMyClass = // 其它对象的指?br>} <br><br>  W二条语句在函数q程中只修改了pMyClass的倹{ƈ没有修改调用者的变量p的倹{?a class=vLink1 id=vad_11 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,11,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,11)" target=_blank name=11>如果</a>p指向某个位于地址0x008a00的对象,当func1q回Ӟ它仍然指向这个特定的对象。(除非func1有bug堆弄ؕ了,完全有这U可能。)<br><br>  现在假设你想要在func1中修改p的倹{这是你的权利。调用者传入一个指针,然后函数l这个指针赋倹{以往一般都是传双指针,x针的指针Q例如,CMyClass**?br><br><br>MYCLASS* p = NULLQ?br>func1Q?amp;pQ;<br><br>void func1QMYCLASS** pMyClassQ;<br>{<br>*pMyClass = new MYCLASSQ?br>……<br>}<br><br><br>  调用func1之后Qp指向新的对象。在COM~程中,你到处都会碰到这L用法--例如?a class=vLink1 id=vad_5 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,5,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,5)" target=_blank name=5>查询</a>对象接口的QueryInterface函数中:<br><br><br>interface ISomeInterface { <br>HRESULT QueryInterfaceQIID &iid, void** ppvObjQ; <br>…… <br>}Q?<br>LPSOMEINTERFACE p=NULLQ?<br>pOb->QueryInterfaceQIID_SOMEINTERFACE, &pQ;  <br><br>  此处Qp是SOMEINTERFACEcd的指针,所?amp;p便是指针的指针,在QueryInterfaceq回的时候,如果调用<a class=vLink1 id=vad_1 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,1,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,1)" target=_blank name=1>成功</a>Q则变量p包含一个指向新的接口的指针?br><br>  如果你理解指针的指针Q那么你肯定q解指针引用,因ؓ它们完全是一回事。如果你?a class=vLink1 id=vad_2 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,2,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,2)" target=_blank name=2>下面</a>q样声明函数Q?br><br><br>void func1QMYCLASS *&pMyClassQ;<br>{<br>pMyClass = new MYCLASSQ?<br>……<br>} <br><br>  其实Q它和前面所讲得指针的指针例子是一码事Q只?a class=vLink1 id=vad_0 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,0,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,0)" target=_blank name=0>语法</a>有所不同。传递的时候不用传p的地址&pQ而是直接传p本nQ?br><br>  MYCLASS* p = NULLQ?br>  func1QpQ;<br><br>  在调用之后,p指向一个新的对象。一般来Ԍ引用的原理或多或就象一个指针,从语法上看它是一个普通变量。所以只要你到*&Q就应该惛_**。也是说这个函CҎ可能修改调用者的指针Q而调用者象普通变量一样传递这个指针,不用地址操作W?amp;?br><br>  至于说什么场合要使用q种ҎQ我会说Q极。MFC在其集合cM用到了它--例如QCObListQ它是一个Cobjects指针列表?br><br><br><br>Class CObList : public Cobject {<br>……<br><br>// 获取/修改指定位置的元?br>Cobject*& GetAtQPOSITION positionQ;<br>Cobject* GetAtQPOSITION positionQ?constQ?br>}Q?br><br><br>  q里有两个GetAt函数Q功能都是获取给定位|的元素。区别何在呢Q?br><br>  区别在于一个让你修改列表中的对象,另一个则不行。所以如果你写成下面q样Q?Cobject* pObj = mylist.GetAtQposQ;<br><br>  则pObj是列表中某个对象的指针,如果接着<a class=vLink1 id=vad_3 onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,3,fxEvent);" style="FONT-SIZE: 1em; CURSOR: pointer; COLOR: #ff3366; BORDER-BOTTOM: #ff3366 1px dotted; TEXT-DECORATION: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted';kwmouseout(this,3)" target=_blank name=3>改变</a>pObj的| pObj = pSomeOtherObjQ?br><br>  qƈ改变不了在位|pos处的对象地址Q而仅仅是改变了变量pObj。但是,如果你写成下面这P Cobject*& rpObj = mylist.GetAtQposQ;<br><br>  现在QrpObj是引用一个列表中的对象的指针Q所以当改变rpObjӞ也会改变列表中位|pos处的对象地址--换句话说Q替代了q个对象。这是Z么CObList会有两个GetAt函数的缘故。一个可以修Ҏ针的|另一个则不能。注意我在此说的是指针,不是对象本n。这两个函数都可以修改对象,但只?&版本可以替代对象?<br><br>  在C/C++中引用是很重要的Q同时也是高效的处理手段。所以要x为C/C++高手Q对引用的概忉|有透彻的理解和熟练的应用是不行的? <img src ="http://www.shnenglu.com/doing5552/aggbug/127994.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/doing5552/" target="_blank">doing5552</a> 2010-09-28 22:06 <a href="http://www.shnenglu.com/doing5552/archive/2010/09/28/127994.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>l说HTML元素的ID和Name属性的区别http://www.shnenglu.com/doing5552/archive/2010/09/22/127323.htmldoing5552doing5552Wed, 22 Sep 2010 02:39:00 GMThttp://www.shnenglu.com/doing5552/archive/2010/09/22/127323.htmlhttp://www.shnenglu.com/doing5552/comments/127323.htmlhttp://www.shnenglu.com/doing5552/archive/2010/09/22/127323.html#Feedback0http://www.shnenglu.com/doing5552/comments/commentRss/127323.htmlhttp://www.shnenglu.com/doing5552/services/trackbacks/127323.html
    上周我也遇到了ID和Name的问题,在页面里输入了一个input type="hidden"Q只写了一个ID='SliceInfo'Q赋值后submitQ在后台用Request.Params["SliceInfo"]却怎么也去不到?img height=19 src="http://www2.cnblogs.com/Emoticons/emdgust.gif" width=19 border=0>。后来恍然大悟因该用Name来标C,于是在input里加了个Name='SliceInfo'Q就一切ok了?br>
    W一D里对于ID和Name的解{说的太W统了,当然那个解释对于ID来说是完全对的,它就是Client端HTML元素的Identity。而Name其实要复杂的多,因ؓName有很多种的用途,所以它q不能完全由ID来代替,从而将其取消掉。具体用途有Q?br>
    用?: 作ؓ可与服务器交互数据的HTML元素的服务器端的标示Q比如input、select、textarea、和button{。我们可以在服务器端Ҏ其Name通过Request.Params取得元素提交的倹{?br>    用?: HTML元素Input type='radio'分组Q我们知道radio button控g在同一个分l类Qcheck操作是mutex的,同一旉只能选中一个radioQ这个分l就是根据相同的Name属性来实现的?br>    用?: 建立面中的锚点Q我们知?lt;a href="URL">link</a>是获得一个页面超U链接,如果不用href属性,而改用NameQ如Q?lt;a name="PageBottom"></a>Q我们就获得了一个页面锚炏V?br>    用?: 作ؓ对象的IdentityQ如Applet、Object、Embed{元素。比如在Applet对象实例中,我们用其Name来引用该对象?br>    用?: 在IMG元素和MAP元素之间兌的时候,如果要定义IMG的热点区域,需要用其属性usemapQusemap="#name"(被关联的MAP元素的Name)?br>    用?: 某些特定元素的属性,如attributeQmeta和param。例如ؓObject定义参数<PARAM NAME = "appletParameter" VALUE = "value">或Meta?lt;META NAME = "Author" CONTENT = "Dave Raggett">?br>
    昄q些用途都不是能简单的使用ID来代替掉的,所以HTML元素的ID和Name的却别ƈ不是w䆾证号码和姓名q样的区别,它们更本是不同作用的东ѝ?br>
    当然HTML元素的Name属性在面中也可以起那么一点ID的作用,因ؓ在DHTML对象树中Q我们可以用document.getElementsByName来获取一个包含页面中所有指定Name元素的对象数l。Name属性还有一个问题,当我们动态创建可包含Name属性的元素Ӟ不能单的使用赋值element.name = "..."来添加其NameQ而必d创徏ElementӞ使用document.createElement('<element name = "myName"></element>')为元素添加Name属性。这是什么意思啊Q看下面的例子就明白了?
<script language="JavaScript">
var input = document.createElement('INPUT');
input.id 
= 'myId';
input.name 
= 'myName';
alert(input.outerHTML);
</script>

    消息框里昄的结果是Q?lt;INPUT id=myId>?/p>

<script language="JavaScript">
var input = document.createElement('<INPUT name="myName">');
input.id 
= 'myId';
alert(input.outerHTML);
</script>

    消息框里昄的结果是Q?lt;INPUT id=myId name=myName>?br>    初始化Name属性的q个设计不是IE的缺P因ؓMSDN里说了要q么做的Q可是这栯计的原理什么呢Q我暂时没有惛_明白?br>
    q里再顺便说一下,要是面中有n(n>1)个HTML元素的ID都相同了怎么办?在DHTML对象中怎么引用他们呢?如果我们使用ASPX面Q这L情况是不Ҏ发生的,因ؓaspnetq程在处理aspx面时根本就不允许有ID非唯一Q这是页面会被抛出异常而不能被正常的render。要是不是动态页面,我们要让ID重复那IE怎么搞呢Q这个时候我们还是可以l用document.getElementById获取对象Q只不过我们只能获取ID重复的那些对象中在HTML Render时第一个出现的对象。而这旉复的ID会在引用时自动变成一个数l,ID重复的元素按Render的顺序依ơ存在于数组中?br>



doing5552 2010-09-22 10:39 发表评论
]]>
鶹Ʒþþþþþ99| ij뾫Ʒþþò| þþƷ| 칫ҾþþƷ| 777ҹƷþav | 99þùۺϾƷ| þþ99ƷƬĻ | 99þþþƷ| ޾Ʒھþ| Ʒ18þþþþvr| þþƷ72| պĻþ| ޾Ʒ99þ| ղƷþþһ| Ʒþþþþþþþ| ŷ糱þþXXXXx| ŷþһwwwwww.| 91ƷɫۺϾþ| 㽶þۺӰ| þûƵ| Ʒ׾þAAAƬ69| þþƷ| þþƷĻһ| þùҹAVӰԺ| þþƷ| 99ŷþþþƷѿ| ˾þô߽AVɫɫ| þþòƷһ | ۺϾþһ | ˾ƷǾþ| ˾Ʒþþþ7777| þۺ¶þü| Ʒþþþþù| һþaþþƷۺ| 69þҹɫƷ69| 99999þþþþ| ɫۺϾþʮ·| Ҫþðѹۿ| ŷһþþƷ޾Ʒþþþ | ݺɫþþۺϲ| ˾þô߽ۺAv |